summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2011-08-02 14:08:58 -0400
committerJason Merrill <jason@gcc.gnu.org>2011-08-02 14:08:58 -0400
commit2b756fa2977b0620d78446b7a97e2c8d7953543c (patch)
tree877c7816cb34d419062402adb5b5edd7c41f80f8
parent979d459888df360b584c17ca72d7a9b76fe50f52 (diff)
downloadgcc-2b756fa2977b0620d78446b7a97e2c8d7953543c.tar.gz
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
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/parser.c62
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for20.C32
4 files changed, 95 insertions, 12 deletions
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 <jason@redhat.com>
+
+ 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 <jakub@redhat.com>
* 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 <jason@redhat.com>
+
+ PR c++/49834
+ * g++.dg/cpp0x/range-for20.C: New.
+
2011-08-02 Tobias Burnus <burnus@net-b.de>
* 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 <typename T> T get_value() const;
+};
+
+struct B {
+ A first, second;
+};
+
+struct C
+{
+ B* begin() const;
+ B* end() const;
+};
+
+template <typename Ret>
+Ret f(const C &p)
+{
+ for (const B &i: p) // OK
+ i.second.get_value<int>();
+ for (const auto &i: p) // ERROR
+ i.second.get_value<int>();
+ return Ret(0);
+}
+
+void g()
+{
+ f<int>(C());
+}