From 2b756fa2977b0620d78446b7a97e2c8d7953543c Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 2 Aug 2011 14:08:58 -0400 Subject: [PATCH] re PR c++/49834 ([C++0x] type deduction in for-each loop in template function) PR c++/49834 * parser.c (build_range_temp): Split out from... (cp_convert_range_for): ...here. (do_range_for_auto_deduction): New. (cp_parser_range_for): Use it. From-SVN: r177199 --- gcc/cp/ChangeLog | 8 +++ gcc/cp/parser.c | 62 +++++++++++++++++++----- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/g++.dg/cpp0x/range-for20.C | 32 ++++++++++++ 4 files changed, 95 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/range-for20.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index bc972a2ac81..bba80e88918 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2011-08-02 Jason Merrill + + PR c++/49834 + * parser.c (build_range_temp): Split out from... + (cp_convert_range_for): ...here. + (do_range_for_auto_deduction): New. + (cp_parser_range_for): Use it. + 2011-08-02 Jakub Jelinek * cp-tree.h (finish_omp_atomic): Adjust prototype. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 576c842e89f..2d8f457e737 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1629,6 +1629,8 @@ static tree cp_parser_c_for (cp_parser *, tree, tree); static tree cp_parser_range_for (cp_parser *, tree, tree, tree); +static void do_range_for_auto_deduction + (tree, tree); static tree cp_parser_perform_range_for_lookup (tree, tree *, tree *); static tree cp_parser_range_for_member_function @@ -8673,6 +8675,7 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl) { stmt = begin_range_for_stmt (scope, init); finish_range_for_decl (stmt, range_decl, range_expr); + do_range_for_auto_deduction (range_decl, range_expr); } else { @@ -8682,6 +8685,52 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl) return stmt; } +/* Subroutine of cp_convert_range_for: given the initializer expression, + builds up the range temporary. */ + +static tree +build_range_temp (tree range_expr) +{ + tree range_type, range_temp; + + /* Find out the type deduced by the declaration + `auto &&__range = range_expr'. */ + range_type = cp_build_reference_type (make_auto (), true); + range_type = do_auto_deduction (range_type, range_expr, + type_uses_auto (range_type)); + + /* Create the __range variable. */ + range_temp = build_decl (input_location, VAR_DECL, + get_identifier ("__for_range"), range_type); + TREE_USED (range_temp) = 1; + DECL_ARTIFICIAL (range_temp) = 1; + + return range_temp; +} + +/* Used by cp_parser_range_for in template context: we aren't going to + do a full conversion yet, but we still need to resolve auto in the + type of the for-range-declaration if present. This is basically + a shortcut version of cp_convert_range_for. */ + +static void +do_range_for_auto_deduction (tree decl, tree range_expr) +{ + tree auto_node = type_uses_auto (TREE_TYPE (decl)); + if (auto_node) + { + tree begin_dummy, end_dummy, range_temp, iter_type, iter_decl; + range_temp = convert_from_reference (build_range_temp (range_expr)); + iter_type = (cp_parser_perform_range_for_lookup + (range_temp, &begin_dummy, &end_dummy)); + iter_decl = build_decl (input_location, VAR_DECL, NULL_TREE, iter_type); + iter_decl = build_x_indirect_ref (iter_decl, RO_NULL, + tf_warning_or_error); + TREE_TYPE (decl) = do_auto_deduction (TREE_TYPE (decl), + iter_decl, auto_node); + } +} + /* Converts a range-based for-statement into a normal for-statement, as per the definition. @@ -8720,7 +8769,6 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl) tree cp_convert_range_for (tree statement, tree range_decl, tree range_expr) { - tree range_type, range_temp; tree begin, end; tree iter_type, begin_expr, end_expr; tree condition, expression; @@ -8731,17 +8779,7 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr) begin_expr = end_expr = iter_type = error_mark_node; else { - /* Find out the type deduced by the declaration - `auto &&__range = range_expr'. */ - range_type = cp_build_reference_type (make_auto (), true); - range_type = do_auto_deduction (range_type, range_expr, - type_uses_auto (range_type)); - - /* Create the __range variable. */ - range_temp = build_decl (input_location, VAR_DECL, - get_identifier ("__for_range"), range_type); - TREE_USED (range_temp) = 1; - DECL_ARTIFICIAL (range_temp) = 1; + tree range_temp = build_range_temp (range_expr); pushdecl (range_temp); cp_finish_decl (range_temp, range_expr, /*is_constant_init*/false, NULL_TREE, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f1c96a0e5f8..3ef97ac5346 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-08-02 Jason Merrill + + PR c++/49834 + * g++.dg/cpp0x/range-for20.C: New. + 2011-08-02 Tobias Burnus * gfortran.dg/coarray_lib_token_3.f90: New. diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for20.C b/gcc/testsuite/g++.dg/cpp0x/range-for20.C new file mode 100644 index 00000000000..8205b228df3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/range-for20.C @@ -0,0 +1,32 @@ +// PR c++/49834 +// { dg-options -std=c++0x } + +struct A +{ + template T get_value() const; +}; + +struct B { + A first, second; +}; + +struct C +{ + B* begin() const; + B* end() const; +}; + +template +Ret f(const C &p) +{ + for (const B &i: p) // OK + i.second.get_value(); + for (const auto &i: p) // ERROR + i.second.get_value(); + return Ret(0); +} + +void g() +{ + f(C()); +} -- 2.30.2