Commit 598a208c by Casey Carter Committed by Jason Merrill

P08184R0: Generalizing the Range-Based For Loop

	* parser.c (cp_convert_range_for): Set the type of __end separately.
	(cp_parser_perform_range_for_lookup): Allow different begin/end
	types if they are comparable.

Co-Authored-By: Jason Merrill <jason@redhat.com>

From-SVN: r234191
parent 3cbf012a
2016-03-14 Casey Carter <casey@carter.net>
Jason Merrill <jason@redhat.com>
P08184R0: Generalizing the Range-Based For Loop
* parser.c (cp_convert_range_for): Set the type of __end separately.
(cp_parser_perform_range_for_lookup): Allow different begin/end
types if they are comparable.
2016-03-12 Patrick Palka <ppalka@gcc.gnu.org>
PR c++/70106
......
......@@ -11353,6 +11353,8 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr,
/*is_constant_init*/false, NULL_TREE,
LOOKUP_ONLYCONVERTING);
if (cxx_dialect >= cxx1z)
iter_type = cv_unqualified (TREE_TYPE (end_expr));
end = build_decl (input_location, VAR_DECL,
get_identifier ("__for_end"), iter_type);
TREE_USED (end) = 1;
......@@ -11488,9 +11490,21 @@ cp_parser_perform_range_for_lookup (tree range, tree *begin, tree *end)
/* The unqualified type of the __begin and __end temporaries should
be the same, as required by the multiple auto declaration. */
if (!same_type_p (iter_type, cv_unqualified (TREE_TYPE (*end))))
error ("inconsistent begin/end types in range-based %<for%> "
"statement: %qT and %qT",
TREE_TYPE (*begin), TREE_TYPE (*end));
{
if (cxx_dialect >= cxx1z
&& (build_x_binary_op (input_location, NE_EXPR,
*begin, ERROR_MARK,
*end, ERROR_MARK,
NULL, tf_none)
!= error_mark_node))
/* P08184R0 allows __begin and __end to have different types,
but make sure they are comparable so we can give a better
diagnostic. */;
else
error ("inconsistent begin/end types in range-based %<for%> "
"statement: %qT and %qT",
TREE_TYPE (*begin), TREE_TYPE (*end));
}
return iter_type;
}
}
......@@ -31,7 +31,7 @@ struct Explicit
void test1()
{
container c;
for (int x : c) // { dg-error "inconsistent|conversion" }
for (int x : c) // { dg-error "inconsistent|conversion|comparison" }
;
int a[2] = {1,2};
......
// P08184R0: Generalizing the Range-Based For Loop
// { dg-options "-std=c++1z" }
struct A {
int ar[4];
int *begin() { return ar; }
struct end_t {
int *p;
friend bool operator!= (int *p, end_t e) { return p != e.p; }
};
end_t end() { return { &ar[4] }; }
};
int main()
{
A a { 1, 2, 3, 4 };
int i = 1;
for (auto x: a)
if (x != i++)
__builtin_abort ();
if (i != 5)
__builtin_abort ();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment