1// PR c++/46056
2// Check that range-based for loop calls destructors
3// when required
4// { dg-do run { target c++11 } }
5extern "C" void abort();
6
7int value_counter = 0, it_counter = 0, seq_counter = 0;
8
9struct Int
10{
11    int x;
12    Int(int v)
13        :x(v)
14    {
15        ++value_counter;
16    }
17    Int(const Int &o)
18        :x(o.x)
19    {
20        ++value_counter;
21    }
22    ~Int()
23    {
24        --value_counter;
25    }
26};
27
28struct iterator
29{
30    int x;
31    iterator(int v)
32        :x(v)
33    {
34        ++it_counter;
35    }
36    iterator(const iterator &o)
37        :x(o.x)
38    {
39        ++it_counter;
40    }
41    ~iterator()
42    {
43        --it_counter;
44    }
45    iterator &operator ++() { ++x; return *this; }
46    int operator *() { return x; }
47    bool operator != (const iterator &o) { return x != o.x; }
48};
49
50struct container
51{
52    int min, max;
53    container(int a, int b) :min(a), max(b)
54    {
55        ++seq_counter;
56    }
57    container(const container &) = delete;
58    ~container()
59    {
60        --seq_counter;
61    }
62};
63
64iterator begin(container &c)
65{
66    return iterator(c.min);
67}
68
69iterator end(container &c)
70{
71    return iterator(c.max + 1);
72}
73
74int main()
75{
76    for (Int x : container(0, 10))
77    {
78        if (value_counter != 1) abort();
79        if (it_counter != 2) abort();
80        if (seq_counter != 1) abort();
81    }
82    if (value_counter != 0) abort();
83    if (it_counter != 0) abort();
84    if (seq_counter != 0) abort();
85
86    try
87    {
88        for (Int x : container(0, 10))
89        {
90            if (value_counter != 1) abort();
91            if (it_counter != 2) abort();
92            if (seq_counter != 1) abort();
93        }
94        if (value_counter != 0) abort();
95        if (it_counter != 0) abort();
96        if (seq_counter != 0) abort();
97
98        for (Int x : container(0, 10))
99        {
100            if (value_counter != 1) abort();
101            if (it_counter != 2) abort();
102            if (seq_counter != 1) abort();
103
104            if (x.x == 5)
105                throw 0;
106        }
107    }
108    catch (int)
109    {
110        if (value_counter != 0) abort();
111        if (it_counter != 0) abort();
112        if (seq_counter != 0) abort();
113    }
114
115    return 0;
116}
117