diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 3a60d0f..4e13a04 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1607,6 +1607,8 @@ static tree cp_parser_c_for
   (cp_parser *, tree, tree);
 static tree cp_parser_range_for
   (cp_parser *, tree, tree, tree);
+static void cp_parser_perform_range_for_lookup
+   (tree, tree *, tree *);
 static tree cp_parser_jump_statement
   (cp_parser *);
 static void cp_parser_declaration_statement
@@ -8555,14 +8557,20 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl)
       }
 
    If RANGE_EXPR is an array:
-       BEGIN_EXPR = __range
-       END_EXPR = __range + ARRAY_SIZE(__range)
+	BEGIN_EXPR = __range
+	END_EXPR = __range + ARRAY_SIZE(__range)
+   Else if RANGE_EXPR has a member 'begin' or 'end':
+	BEGIN_EXPR = __range.begin()
+	END_EXPR = __range.end()
    Else:
 	BEGIN_EXPR = begin(__range)
 	END_EXPR = end(__range);
 
-   When calling begin()/end() we must use argument dependent
-   lookup, but always considering 'std' as an associated namespace.  */
+   If __range has a member 'begin' but not 'end', or vice versa, we must
+   still use the second alternative (it will surely fail, however).
+   When calling begin()/end() in the third alternative we must use
+   argument dependent lookup, but always considering 'std' as an associated
+   namespace.  */
 
 tree
 cp_convert_range_for (tree statement, tree range_decl, tree range_expr)
@@ -8598,44 +8606,41 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr)
 
       if (TREE_CODE (TREE_TYPE (range_temp)) == ARRAY_TYPE)
 	{
-	  /* If RANGE_TEMP is an array we will use pointer arithmetic */
-	  iter_type = build_pointer_type (TREE_TYPE (TREE_TYPE (range_temp)));
-	  begin_expr = range_temp;
-	  end_expr
-	      = build_binary_op (input_location, PLUS_EXPR,
-				 range_temp,
-				 array_type_nelts_top (TREE_TYPE (range_temp)),
-				 0);
+	  if (!COMPLETE_TYPE_P (TREE_TYPE (range_temp)))
+	    {
+	      error ("range-based-for expression must be of a complete type");
+	      begin_expr = end_expr = iter_type = error_mark_node;
+	    }
+	  else
+	    {
+	      /* If RANGE_TEMP is an array we will use pointer arithmetic */
+	      iter_type = build_pointer_type (TREE_TYPE (TREE_TYPE (range_temp)));
+	      begin_expr = range_temp;
+	      end_expr
+		  = build_binary_op (input_location, PLUS_EXPR,
+				     range_temp,
+				     array_type_nelts_top (TREE_TYPE (range_temp)),
+				     0);
+	    }
 	}
       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));
+	  cp_parser_perform_range_for_lookup (range_temp, &begin_expr, &end_expr);
+
+	  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));
+	      /* 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));
+	    }
 	}
     }
 
@@ -8680,6 +8685,84 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr)
   return statement;
 }
 
+static void
+cp_parser_perform_range_for_lookup (tree range, tree *begin, tree *end)
+{
+  tree id_begin, id_end;
+
+  id_begin = get_identifier ("begin");
+  *begin = build_qualified_name (/*type=*/NULL_TREE,
+				     TREE_TYPE (range),
+				     id_begin,
+				     /*template_p=*/false);
+  *begin = finish_class_member_access_expr(range, *begin,
+					       false, tf_none);
+
+  id_end = get_identifier ("end");
+  *end = build_qualified_name (/*type=*/NULL_TREE,
+			       TREE_TYPE (range),
+			       id_end,
+			       /*template_p=*/false);
+  *end = finish_class_member_access_expr(range, *end,
+					 false, tf_none);
+
+  VEC(tree,gc) *vec;
+  vec = make_tree_vector ();
+
+  if (*begin != error_mark_node || *end != error_mark_node)
+    {
+      if (*begin != error_mark_node)
+	{
+	  tree instance = TREE_OPERAND (*begin, 0);
+	  tree fn = TREE_OPERAND (*begin, 1);
+	  if (BASELINK_P (fn))
+	    *begin = build_new_method_call (instance, fn,
+					    NULL, NULL, LOOKUP_NORMAL,
+					    NULL, tf_warning_or_error);
+	  else
+	    *begin = finish_call_expr (*begin, &vec,
+				       /*disallow_virtual=*/false,
+				       /*koenig_p=*/false,
+				       tf_warning_or_error);
+	}
+      else
+	error ("range-based-for expression has an %<end%> member "
+	       "but not a %<begin%>");
+      if (*end != error_mark_node)
+	{
+	  tree instance = TREE_OPERAND (*end, 0);
+	  tree fn = TREE_OPERAND (*end, 1);
+	  if (BASELINK_P (fn))
+	    *end = build_new_method_call (instance, fn,
+					  NULL, NULL, LOOKUP_NORMAL,
+					  NULL, tf_warning_or_error);
+	  else
+	    *end = finish_call_expr (*end, &vec,
+				     /*disallow_virtual=*/false,
+				     /*koenig_p=*/false,
+				     tf_warning_or_error);
+	}
+      else
+	error ("range-based-for expression has a %<begin%> member "
+	       "but not an %<end%>");
+    }
+  else
+    {
+      VEC_safe_push (tree, gc, vec, range);
+
+      *begin = perform_koenig_lookup (id_begin, vec,
+					  /*include_std=*/true);
+      *begin = finish_call_expr (*begin, &vec, false, true,
+				 tf_warning_or_error);
+      *end = perform_koenig_lookup (id_end, vec,
+					/*include_std=*/true);
+      *end = finish_call_expr (*end, &vec, false, true,
+			       tf_warning_or_error);
+
+    }
+  release_tree_vector (vec);
+}
+
 
 /* Parse an iteration-statement.
 
