> Yes, I was just trying exactly that improvement.
How about this?
> I'm going to let the committee know that option 5 has been
> implemented. Thanks very much!
Cool! Thank you.
--
Rodrigo
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 9523fdc..aab9294 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1871,6 +1871,8 @@ static tree cp_parser_c_for
(cp_parser *, tree, tree);
static tree cp_parser_range_for
(cp_parser *, tree, tree, tree);
+static tree cp_parser_perform_range_for_lookup
+ (const char *, tree, int*);
static tree cp_parser_jump_statement
(cp_parser *);
static void cp_parser_declaration_statement
@@ -8870,32 +8872,34 @@ cp_convert_range_for (tree statement, tree range_decl,
tree range_expr)
else
{
/* If it is not an array, we must call begin(__range)/end__range() */
- VEC(tree,gc) *vec;
-
- begin_expr = get_identifier ("begin");
- vec = make_tree_vector ();
- VEC_safe_push (tree, gc, vec, range_temp);
- begin_expr = perform_koenig_lookup (begin_expr, vec,
- /*include_std=*/true);
- begin_expr = finish_call_expr (begin_expr, &vec, false, true,
- tf_warning_or_error);
- release_tree_vector (vec);
-
- end_expr = get_identifier ("end");
- vec = make_tree_vector ();
- VEC_safe_push (tree, gc, vec, range_temp);
- end_expr = perform_koenig_lookup (end_expr, vec,
- /*include_std=*/true);
- end_expr = finish_call_expr (end_expr, &vec, false, true,
- tf_warning_or_error);
- release_tree_vector (vec);
-
- /* The unqualified type of the __begin and __end temporaries should
- * be the same as required by the multiple auto declaration */
- iter_type = cv_unqualified (TREE_TYPE (begin_expr));
- if (!same_type_p (iter_type, cv_unqualified (TREE_TYPE (end_expr))))
- error ("inconsistent begin/end types in range-based for: %qT and
%qT",
- TREE_TYPE (begin_expr), TREE_TYPE (end_expr));
+ int begin_is_member = 0;
+ begin_expr = cp_parser_perform_range_for_lookup("begin", range_temp,
&begin_is_member);
+ int end_is_member = 0;
+ end_expr = cp_parser_perform_range_for_lookup("end", range_temp,
&end_is_member);
+
+ if (begin_expr == error_mark_node || end_expr == error_mark_node)
+ /* If one of the expressions is an error do no more checks. */
+ begin_expr = end_expr = iter_type = error_mark_node;
+ else
+ {
+ iter_type = cv_unqualified (TREE_TYPE (begin_expr));
+ /* Check that the __begin and __end expressions are consistent.
*/
+ if (begin_is_member != end_is_member)
+ {
+ error ("range-based for found %s %<begin%> and %s %<end%>",
+ (begin_is_member ? "member" : "non-member"),
+ (end_is_member ? "member" : "non-member"));
+ }
+ else
+ {
+ /* 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_expr))))
+ error ("inconsistent begin/end types in range-based for: "
+ "%qT and %qT",
+ TREE_TYPE (begin_expr), TREE_TYPE (end_expr));
+ }
+ }
}
}
@@ -8940,6 +8944,44 @@ cp_convert_range_for (tree statement, tree range_decl,
tree range_expr)
return statement;
}
+static tree
+cp_parser_perform_range_for_lookup (const char *name, tree range, int*
is_member)
+{
+ tree ident, expr;
+
+ ident = get_identifier (name);
+ expr = build_qualified_name (/*type=*/NULL_TREE,
+ TREE_TYPE (range),
+ ident,
+ /*template_p=*/false);
+ expr = finish_class_member_access_expr(range, expr, false, tf_none);
+
+ if (expr != error_mark_node)
+ {
+ tree instance, fn;
+ instance = TREE_OPERAND (expr, 0);
+ fn = TREE_OPERAND (expr, 1);
+
+ expr = build_new_method_call (instance, fn, NULL, NULL, LOOKUP_NORMAL,
+ NULL, tf_warning_or_error);
+ *is_member = 1;
+ }
+ else
+ {
+ VEC(tree,gc) *vec;
+ vec = make_tree_vector ();
+ VEC_safe_push (tree, gc, vec, range);
+ expr = get_identifier (name);
+ expr = perform_koenig_lookup (expr, vec,
+ /*include_std=*/true);
+ expr = finish_call_expr (expr, &vec, false, true,
+ tf_warning_or_error);
+ release_tree_vector (vec);
+ *is_member = 0;
+ }
+ return expr;
+}
+
/* Parse an iteration-statement.