> 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.