From 30ca47e6eb445c98ac17f0d849c45b6389b40297 Mon Sep 17 00:00:00 2001 From: Rodrigo Rivas Costa Date: Wed, 20 Oct 2010 14:13:38 +0000 Subject: [PATCH] re PR c++/46056 ([C++0x] range-based for loop does not destruct iterators) PR c++/46056 * parser.c (cp_convert_range_for): Call cp_finish_decl instead of finish_expr_stmt. From-SVN: r165726 --- gcc/cp/ChangeLog | 6 ++ gcc/cp/parser.c | 18 ++-- gcc/testsuite/ChangeLog | 5 + gcc/testsuite/g++.dg/cpp0x/range-for7.C | 117 ++++++++++++++++++++++++ 4 files changed, 139 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/range-for7.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 7343b2d4cc6..2d6a17d3680 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2010-10-20 Rodrigo Rivas Costa + + PR c++/46056 + * parser.c (cp_convert_range_for): Call cp_finish_decl + instead of finish_expr_stmt. + 2010-10-20 Nicola Pero * cp-lang.c (finish_file): Removed. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 477348661bd..8c0129ba26b 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -8773,8 +8773,10 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr) 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,16 +8826,18 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr) 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); - - finish_expr_stmt (cp_build_modify_expr (end, INIT_EXPR, end_expr, - tf_warning_or_error)); + cp_finish_decl (end, end_expr, + /*is_constant_init*/false, NULL_TREE, + LOOKUP_ONLYCONVERTING); finish_for_init_stmt (statement); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 519f7a7fb63..2811af57d87 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-10-20 Rodrigo Rivas Costa + + PR c++/46056 + * g++.dg/cpp0x/range-for7.C: New. + 2010-10-20 Richard Guenther PR lto/45667 diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for7.C b/gcc/testsuite/g++.dg/cpp0x/range-for7.C new file mode 100644 index 00000000000..ad89dc201b6 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/range-for7.C @@ -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; +}