===================================================================
@@ -8773,8 +8773,10 @@ cp_convert_range_for (tree statement, tree range_d
TREE_USED (range_temp) = 1;
DECL_ARTIFICIAL (range_temp) = 1;
pushdecl (range_temp);
- finish_expr_stmt (cp_build_modify_expr (range_temp, INIT_EXPR, range_expr,
- tf_warning_or_error));
+ cp_finish_decl (range_temp, range_expr,
+ /*is_constant_init*/false, NULL_TREE,
+ LOOKUP_ONLYCONVERTING);
+
range_temp = convert_from_reference (range_temp);
if (TREE_CODE (TREE_TYPE (range_temp)) == ARRAY_TYPE)
@@ -8824,17 +8826,19 @@ cp_convert_range_for (tree statement, tree range_d
TREE_USED (begin) = 1;
DECL_ARTIFICIAL (begin) = 1;
pushdecl (begin);
- finish_expr_stmt (cp_build_modify_expr (begin, INIT_EXPR, begin_expr,
- tf_warning_or_error));
+ cp_finish_decl (begin, begin_expr,
+ /*is_constant_init*/false, NULL_TREE,
+ LOOKUP_ONLYCONVERTING);
+
end = build_decl (input_location, VAR_DECL,
get_identifier ("__for_end"), iter_type);
TREE_USED (end) = 1;
DECL_ARTIFICIAL (end) = 1;
pushdecl (end);
+ cp_finish_decl (end, end_expr,
+ /*is_constant_init*/false, NULL_TREE,
+ LOOKUP_ONLYCONVERTING);
- finish_expr_stmt (cp_build_modify_expr (end, INIT_EXPR, end_expr,
- tf_warning_or_error));
-
finish_for_init_stmt (statement);
/* The new for condition */
===================================================================
@@ -0,0 +1,117 @@
+// PR c++/46056
+// Check that range-based for loop calls destructors
+// when required
+// { dg-options "-std=c++0x" }
+// { dg-do run }
+extern "C" void abort();
+
+int value_counter = 0, it_counter = 0, seq_counter = 0;
+
+struct Int
+{
+ int x;
+ Int(int v)
+ :x(v)
+ {
+ ++value_counter;
+ }
+ Int(const Int &o)
+ :x(o.x)
+ {
+ ++value_counter;
+ }
+ ~Int()
+ {
+ --value_counter;
+ }
+};
+
+struct iterator
+{
+ int x;
+ iterator(int v)
+ :x(v)
+ {
+ ++it_counter;
+ }
+ iterator(const iterator &o)
+ :x(o.x)
+ {
+ ++it_counter;
+ }
+ ~iterator()
+ {
+ --it_counter;
+ }
+ iterator &operator ++() { ++x; return *this; }
+ int operator *() { return x; }
+ bool operator != (const iterator &o) { return x != o.x; }
+};
+
+struct container
+{
+ int min, max;
+ container(int a, int b) :min(a), max(b)
+ {
+ ++seq_counter;
+ }
+ container(const container &) = delete;
+ ~container()
+ {
+ --seq_counter;
+ }
+};
+
+iterator begin(container &c)
+{
+ return iterator(c.min);
+}
+
+iterator end(container &c)
+{
+ return iterator(c.max + 1);
+}
+
+int main()
+{
+ for (Int x : container(0, 10))
+ {
+ if (value_counter != 1) abort();
+ if (it_counter != 2) abort();
+ if (seq_counter != 1) abort();
+ }
+ if (value_counter != 0) abort();
+ if (it_counter != 0) abort();
+ if (seq_counter != 0) abort();
+
+ try
+ {
+ for (Int x : container(0, 10))
+ {
+ if (value_counter != 1) abort();
+ if (it_counter != 2) abort();
+ if (seq_counter != 1) abort();
+ }
+ if (value_counter != 0) abort();
+ if (it_counter != 0) abort();
+ if (seq_counter != 0) abort();
+
+ for (Int x : container(0, 10))
+ {
+ if (value_counter != 1) abort();
+ if (it_counter != 2) abort();
+ if (seq_counter != 1) abort();
+
+ if (x.x == 5)
+ throw 0;
+ }
+ }
+ catch (int)
+ {
+ if (value_counter != 0) abort();
+ if (it_counter != 0) abort();
+ if (seq_counter != 0) abort();
+ }
+
+ return 0;
+}