summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2011-04-16 00:28:17 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2011-04-16 00:28:17 +0000
commit4e81a9f33d5f19ce608e03fc28919f9705baa739 (patch)
treef935ef5d5afe9c68c523e956499fa96210611ab5
parent33235920a45adb442ff095277c20ca0b0de82b4e (diff)
downloadgcc-4e81a9f33d5f19ce608e03fc28919f9705baa739.tar.gz
Implement N3271
* parser.c (cp_convert_range_for): Split into cp_parser_perform_range_for_lookup. (cp_parser_perform_range_for_lookup): New. (cp_parser_range_for_member_function): New. (cp_parser_for_init_statement): Correct error message. * semantics.c (finish_call_expr): Accept COMPONENT_REF. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@172531 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/parser.c194
-rw-r--r--gcc/cp/semantics.c16
-rw-r--r--gcc/testsuite/ChangeLog16
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for11.C40
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for12.C116
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for13.C103
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for14.C95
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for15.C59
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for16.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for17.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for2.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for3.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for9.C2
14 files changed, 639 insertions, 58 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 80c96e1e60b..aae532a8e1a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,13 @@
+2011-04-15 Rodrigo Rivas Costa <rodrigorivascosta@gmail.com>
+
+ Implement N3271
+ * parser.c (cp_convert_range_for): Split into
+ cp_parser_perform_range_for_lookup.
+ (cp_parser_perform_range_for_lookup): New.
+ (cp_parser_range_for_member_function): New.
+ (cp_parser_for_init_statement): Correct error message.
+ * semantics.c (finish_call_expr): Accept COMPONENT_REF.
+
2011-04-14 Nicola Pero <nicola.pero@meta-innovation.com>
* parser.c (cp_parser_objc_protocol_declaration): Updated for
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index ba331aeda71..2c7ace6bbb9 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1607,6 +1607,10 @@ 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
+ (tree, tree *, tree *);
+static tree cp_parser_range_for_member_function
+ (tree, tree);
static tree cp_parser_jump_statement
(cp_parser *);
static void cp_parser_declaration_statement
@@ -8557,14 +8561,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)
@@ -8581,12 +8591,12 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr)
else
{
/* Find out the type deduced by the declaration
- * `auto &&__range = range_expr' */
+ `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 */
+ /* Create the __range variable. */
range_temp = build_decl (input_location, VAR_DECL,
get_identifier ("__for_range"), range_type);
TREE_USED (range_temp) = 1;
@@ -8597,51 +8607,11 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr)
LOOKUP_ONLYCONVERTING);
range_temp = convert_from_reference (range_temp);
-
- 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);
- }
- 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));
- }
+ iter_type = cp_parser_perform_range_for_lookup (range_temp,
+ &begin_expr, &end_expr);
}
- /* The new for initialization statement */
+ /* The new for initialization statement. */
begin = build_decl (input_location, VAR_DECL,
get_identifier ("__for_begin"), iter_type);
TREE_USED (begin) = 1;
@@ -8662,18 +8632,18 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr)
finish_for_init_stmt (statement);
-/* The new for condition */
+ /* The new for condition. */
condition = build_x_binary_op (NE_EXPR,
begin, ERROR_MARK,
end, ERROR_MARK,
NULL, tf_warning_or_error);
finish_for_cond (condition, statement);
- /* The new increment expression */
+ /* The new increment expression. */
expression = finish_unary_op_expr (PREINCREMENT_EXPR, begin);
finish_for_expr (expression, statement);
- /* The declaration is initialized with *__begin inside the loop body */
+ /* The declaration is initialized with *__begin inside the loop body. */
cp_finish_decl (range_decl,
build_x_indirect_ref (begin, RO_NULL, tf_warning_or_error),
/*is_constant_init*/false, NULL_TREE,
@@ -8682,6 +8652,124 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr)
return statement;
}
+/* Solves BEGIN_EXPR and END_EXPR as described in cp_convert_range_for.
+ We need to solve both at the same time because the method used
+ depends on the existence of members begin or end.
+ Returns the type deduced for the iterator expression. */
+
+static tree
+cp_parser_perform_range_for_lookup (tree range, tree *begin, tree *end)
+{
+ if (!COMPLETE_TYPE_P (TREE_TYPE (range)))
+ {
+ error ("range-based %<for%> expression of type %qT "
+ "has incomplete type", TREE_TYPE (range));
+ *begin = *end = error_mark_node;
+ return error_mark_node;
+ }
+ if (TREE_CODE (TREE_TYPE (range)) == ARRAY_TYPE)
+ {
+ /* If RANGE is an array, we will use pointer arithmetic. */
+ *begin = range;
+ *end = build_binary_op (input_location, PLUS_EXPR,
+ range,
+ array_type_nelts_top (TREE_TYPE (range)),
+ 0);
+ return build_pointer_type (TREE_TYPE (TREE_TYPE (range)));
+ }
+ else
+ {
+ /* If it is not an array, we must do a bit of magic. */
+ tree id_begin, id_end;
+ tree member_begin, member_end;
+
+ *begin = *end = error_mark_node;
+
+ id_begin = get_identifier ("begin");
+ id_end = get_identifier ("end");
+ member_begin = lookup_member (TREE_TYPE (range), id_begin,
+ /*protect=*/2, /*want_type=*/false);
+ member_end = lookup_member (TREE_TYPE (range), id_end,
+ /*protect=*/2, /*want_type=*/false);
+
+ if (member_begin != NULL_TREE || member_end != NULL_TREE)
+ {
+ /* Use the member functions. */
+ if (member_begin != NULL_TREE)
+ *begin = cp_parser_range_for_member_function (range, id_begin);
+ else
+ error ("range-based %<for%> expression of type %qT has an "
+ "%<end%> member but not a %<begin%>", TREE_TYPE (range));
+
+ if (member_end != NULL_TREE)
+ *end = cp_parser_range_for_member_function (range, id_end);
+ else
+ error ("range-based %<for%> expression of type %qT has a "
+ "%<begin%> member but not an %<end%>", TREE_TYPE (range));
+ }
+ else
+ {
+ /* Use global functions with ADL. */
+ VEC(tree,gc) *vec;
+ vec = make_tree_vector ();
+
+ VEC_safe_push (tree, gc, vec, range);
+
+ member_begin = perform_koenig_lookup (id_begin, vec,
+ /*include_std=*/true);
+ *begin = finish_call_expr (member_begin, &vec, false, true,
+ tf_warning_or_error);
+ member_end = perform_koenig_lookup (id_end, vec,
+ /*include_std=*/true);
+ *end = finish_call_expr (member_end, &vec, false, true,
+ tf_warning_or_error);
+
+ release_tree_vector (vec);
+ }
+
+ /* Last common checks. */
+ if (*begin == error_mark_node || *end == error_mark_node)
+ {
+ /* If one of the expressions is an error do no more checks. */
+ *begin = *end = error_mark_node;
+ return error_mark_node;
+ }
+ else
+ {
+ tree iter_type = cv_unqualified (TREE_TYPE (*begin));
+ /* 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));
+ return iter_type;
+ }
+ }
+}
+
+/* Helper function for cp_parser_perform_range_for_lookup.
+ Builds a tree for RANGE.IDENTIFIER(). */
+
+static tree
+cp_parser_range_for_member_function (tree range, tree identifier)
+{
+ tree member, res;
+ VEC(tree,gc) *vec;
+
+ member = finish_class_member_access_expr (range, identifier,
+ false, tf_warning_or_error);
+ if (member == error_mark_node)
+ return error_mark_node;
+
+ vec = make_tree_vector ();
+ res = finish_call_expr (member, &vec,
+ /*disallow_virtual=*/false,
+ /*koenig_p=*/false,
+ tf_warning_or_error);
+ release_tree_vector (vec);
+ return res;
+}
/* Parse an iteration-statement.
@@ -8830,7 +8918,7 @@ cp_parser_for_init_statement (cp_parser* parser, tree *decl)
if (cxx_dialect < cxx0x)
{
error_at (cp_lexer_peek_token (parser->lexer)->location,
- "range-based-for loops are not allowed "
+ "range-based %<for%> loops are not allowed "
"in C++98 mode");
*decl = error_mark_node;
}
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index b7171ed324b..793883e8982 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2074,6 +2074,22 @@ finish_call_expr (tree fn, VEC(tree,gc) **args, bool disallow_virtual,
make_args_non_dependent (*args);
}
+ if (TREE_CODE (fn) == COMPONENT_REF)
+ {
+ tree member = TREE_OPERAND (fn, 1);
+ if (BASELINK_P (member))
+ {
+ tree object = TREE_OPERAND (fn, 0);
+ return build_new_method_call (object, member,
+ args, NULL_TREE,
+ (disallow_virtual
+ ? LOOKUP_NORMAL | LOOKUP_NONVIRTUAL
+ : LOOKUP_NORMAL),
+ /*fn_p=*/NULL,
+ complain);
+ }
+ }
+
if (is_overloaded_fn (fn))
fn = baselink_for_fns (fn);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d8cc8833889..ea66b492b77 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,19 @@
+2011-04-15 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp0x/range-for17.C: New.
+
+2011-04-15 Rodrigo Rivas Costa <rodrigorivascosta@gmail.com>
+
+ * g++.dg/cpp0x/range-for2.C: Correct for declaration.
+ * g++.dg/cpp0x/range-for3.C: Likewise.
+ * g++.dg/cpp0x/range-for9.C: Correct error message.
+ * g++.dg/cpp0x/range-for11.C: New.
+ * g++.dg/cpp0x/range-for12.C: New.
+ * g++.dg/cpp0x/range-for13.C: New.
+ * g++.dg/cpp0x/range-for14.C: New.
+ * g++.dg/cpp0x/range-for15.C: New.
+ * g++.dg/cpp0x/range-for16.C: New.
+
2011-04-15 Tobias Burnus <burnus@net-b.de>
PR fortran/18918
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for11.C b/gcc/testsuite/g++.dg/cpp0x/range-for11.C
new file mode 100644
index 00000000000..d02519a2519
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for11.C
@@ -0,0 +1,40 @@
+// Test for range-based for loop
+// Test the loop with a custom iterator
+// with begin/end as member functions
+
+// { dg-do compile }
+// { dg-options "-std=c++0x" }
+
+struct iterator
+{
+ int x;
+ explicit iterator(int v) :x(v) {}
+ iterator &operator ++() { ++x; return *this; }
+ int operator *() { return x; }
+ bool operator != (const iterator &o) { return x != o.x; }
+};
+
+namespace foo
+{
+ struct container
+ {
+ int min, max;
+ container(int a, int b) :min(a), max(b) {}
+
+ iterator begin()
+ {
+ return iterator(min);
+ }
+ iterator end()
+ {
+ return iterator(max + 1);
+ }
+ };
+}
+
+int main()
+{
+ foo::container c(1,4);
+ for (int it : c)
+ ;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for12.C b/gcc/testsuite/g++.dg/cpp0x/range-for12.C
new file mode 100644
index 00000000000..9b405dc620a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for12.C
@@ -0,0 +1,116 @@
+// Test for range-based for loop with templates
+// and begin/end as member functions
+
+// { dg-do run }
+// { dg-options "-std=c++0x" }
+
+/* Preliminary declarations */
+namespace pre
+{
+ struct iterator
+ {
+ int x;
+ explicit iterator (int v) :x(v) {}
+ iterator &operator ++() { ++x; return *this; }
+ int operator *() { return x; }
+ bool operator != (const iterator &o) { return x != o.x; }
+ };
+
+ struct container
+ {
+ int min, max;
+ container(int a, int b) :min(a), max(b) {}
+ iterator begin() const
+ {
+ return iterator(min);
+ }
+ iterator end() const
+ {
+ return iterator(max);
+ }
+
+ };
+
+} //namespace pre
+
+using pre::container;
+extern "C" void abort(void);
+
+container run_me_just_once()
+{
+ static bool run = false;
+ if (run)
+ abort();
+ run = true;
+ return container(1,2);
+}
+
+/* Template with dependent expression. */
+template<typename T> int test1(const T &r)
+{
+ int t = 0;
+ for (int i : r)
+ t += i;
+ return t;
+}
+
+/* Template with non-dependent expression and dependent declaration. */
+template<typename T> int test2(const container &r)
+{
+ int t = 0;
+ for (T i : r)
+ t += i;
+ return t;
+}
+
+/* Template with non-dependent expression (array) and dependent declaration. */
+template<typename T> int test2(const int (&r)[4])
+{
+ int t = 0;
+ for (T i : r)
+ t += i;
+ return t;
+}
+
+/* Template with non-dependent expression and auto declaration. */
+template<typename T> int test3(const container &r)
+{
+ int t = 0;
+ for (auto i : r)
+ t += i;
+ return t;
+}
+
+/* Template with non-dependent expression (array) and auto declaration. */
+template<typename T> int test3(const int (&r)[4])
+{
+ int t = 0;
+ for (auto i : r)
+ t += i;
+ return t;
+}
+
+int main ()
+{
+ container c(1,5);
+ int a[4] = {5,6,7,8};
+
+ for (auto x : run_me_just_once())
+ ;
+
+ if (test1 (c) != 10)
+ abort();
+ if (test1 (a) != 26)
+ abort();
+
+ if (test2<int> (c) != 10)
+ abort();
+ if (test2<int> (a) != 26)
+ abort();
+
+ if (test3<int> (c) != 10)
+ abort();
+ if (test3<int> (a) != 26)
+ abort();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for13.C b/gcc/testsuite/g++.dg/cpp0x/range-for13.C
new file mode 100644
index 00000000000..7ebf0c563e8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for13.C
@@ -0,0 +1,103 @@
+// Test for errors in range-based for loops
+// with member begin/end
+
+// { dg-do compile }
+// { dg-options "-std=c++0x" }
+
+//These should not be used
+template<typename T> int *begin(T &t)
+{
+ T::fail;
+}
+template<typename T> int *end(T &t)
+{
+ T::fail;
+}
+
+struct container1
+{
+ int *begin();
+ //no end
+};
+
+struct container2
+{
+ int *end();
+ //no begin
+};
+
+struct container3
+{
+private:
+ int *begin(); // { dg-error "is private" }
+ int *end(); // { dg-error "is private" }
+};
+
+struct container4
+{
+ int *begin;
+ int *end;
+};
+
+struct container5
+{
+ typedef int *begin;
+ typedef int *end;
+};
+
+struct callable
+{
+ int *operator()();
+};
+
+struct container6
+{
+ callable begin;
+ callable end;
+};
+
+struct container7
+{
+ static callable begin;
+ static callable end;
+};
+
+struct container8
+{
+ static int *begin();
+ int *end();
+};
+
+struct private_callable
+{
+private:
+ int *operator()(); // { dg-error "is private" }
+};
+
+struct container9
+{
+ private_callable begin;
+ private_callable end;
+};
+
+struct container10
+{
+ typedef int *(*function)();
+
+ function begin;
+ static function end;
+};
+
+void test1()
+{
+ for (int x : container1()); // { dg-error "member but not" }
+ for (int x : container2()); // { dg-error "member but not" }
+ for (int x : container3()); // { dg-error "within this context" }
+ for (int x : container4()); // { dg-error "cannot be used as a function" }
+ for (int x : container5()); // { dg-error "invalid use of" }
+ for (int x : container6());
+ for (int x : container7());
+ for (int x : container8());
+ for (int x : container9()); // { dg-error "within this context" }
+ for (int x : container10());
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for14.C b/gcc/testsuite/g++.dg/cpp0x/range-for14.C
new file mode 100644
index 00000000000..26ae477d70e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for14.C
@@ -0,0 +1,95 @@
+// Test for other range-based for loops with
+// begin/end member functions
+
+// { dg-do compile }
+// { dg-options "-std=c++0x" }
+
+//These should not be used
+template<typename T> int *begin(T &t)
+{
+ T::fail;
+}
+template<typename T> int *end(T &t)
+{
+ T::fail;
+}
+
+//Test for defaults
+
+struct default1
+{
+ int *begin(int x); // { dg-message "note" }
+ int *end();
+};
+
+struct default2
+{
+ int *begin(int x=0);
+ int *end();
+};
+
+struct default3
+{
+ template <typename T> T *begin(); // { dg-message "note" }
+ int *end();
+};
+
+struct default4
+{
+ template <typename T=int> T *begin();
+ int *end();
+};
+
+struct default5
+{
+ template <typename T=int> T *begin(int x=0);
+ int *end();
+};
+
+void test1()
+{
+ for (int x : default1()); // { dg-error "no matching function|note" }
+ for (int x : default2());
+ for (int x : default3()); // { dg-error "no matching function|note" }
+ for (int x : default4());
+ for (int x : default5());
+}
+
+//Inheritance tests
+
+struct base_begin
+{
+ int *begin(); // { dg-error "" }
+};
+
+struct base_end
+{
+ int *end();
+};
+
+struct derived1 : base_begin, base_end
+{
+};
+
+struct base_begin2 : base_begin
+{
+};
+
+struct derived2 : base_begin, base_end, base_begin2 // { dg-warning "" }
+{
+};
+
+struct base_begin3 : virtual base_begin
+{
+};
+
+struct derived3 : virtual base_begin, base_end, base_begin3
+{
+};
+
+void test2()
+{
+ for (int x : derived1());
+ for (int x : derived2()); // { dg-error "is ambiguous" }
+ for (int x : derived3());
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for15.C b/gcc/testsuite/g++.dg/cpp0x/range-for15.C
new file mode 100644
index 00000000000..38f330771ea
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for15.C
@@ -0,0 +1,59 @@
+// Test for range-based for loop with templates
+// and begin/end as member (non-)virtual functions
+
+// { dg-do run }
+// { dg-options "-std=c++0x" }
+
+unsigned int g;
+
+struct A
+{
+ virtual int *begin()
+ {
+ g |= 1;
+ return 0;
+ }
+ int *end()
+ {
+ g |= 2;
+ return 0;
+ }
+};
+
+struct B : A
+{
+ virtual int *begin()
+ {
+ g |= 4;
+ return 0;
+ }
+ int *end()
+ {
+ g |= 8;
+ return 0;
+ }
+};
+
+extern "C" void abort(void);
+
+int main ()
+{
+ A a;
+ B b;
+ A &aa = b;
+
+ g = 0;
+ for (int x : a);
+ if (g != (1 | 2))
+ abort();
+
+ g = 0;
+ for (int x : b);
+ if (g != (4 | 8))
+ abort();
+
+ g = 0;
+ for (int x : aa);
+ if (g != (4 | 2))
+ abort();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for16.C b/gcc/testsuite/g++.dg/cpp0x/range-for16.C
new file mode 100644
index 00000000000..86cc2a828bf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for16.C
@@ -0,0 +1,21 @@
+// Test for range-based for loop with arrays of
+// incomplete type or unknown size
+
+// { dg-do compile }
+// { dg-options "-std=c++0x" }
+
+extern int a[10];
+extern int b[];
+
+struct S;
+extern S c[10];
+extern S d[];
+
+void test()
+{
+ for (int n : a);
+ for (int n : b); // { dg-error "incomplete type" }
+ for (S &n : c); // { dg-error "incomplete type" }
+ for (S &n : d); // { dg-error "incomplete type" }
+ for (int n : *c); // { dg-error "incomplete type" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for17.C b/gcc/testsuite/g++.dg/cpp0x/range-for17.C
new file mode 100644
index 00000000000..eb888d9ab62
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for17.C
@@ -0,0 +1,17 @@
+// { dg-options -std=c++0x }
+
+extern "C" int printf (const char *, ...);
+
+enum E { e1, e2, e3, X };
+E operator*(E e) { return e; }
+E begin(E e) { return e; }
+E end(E e) { return X; };
+E operator++(E& e) { return e = E(e+1); }
+
+int main()
+{
+ for (auto e: e1)
+ {
+ printf ("%d ", e);
+ }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for2.C b/gcc/testsuite/g++.dg/cpp0x/range-for2.C
index bfab37673a1..17eb41dba7b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for2.C
@@ -8,7 +8,7 @@
struct iterator
{
int x;
- iterator(int v) :x(v) {}
+ explicit iterator(int v) :x(v) {}
iterator &operator ++() { ++x; return *this; }
int operator *() { return x; }
bool operator != (const iterator &o) { return x != o.x; }
@@ -36,6 +36,6 @@ namespace foo
int main()
{
foo::container c(1,4);
- for (iterator it : c)
+ for (int it : c)
;
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for3.C b/gcc/testsuite/g++.dg/cpp0x/range-for3.C
index 947f01ced74..85115a38f5e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for3.C
@@ -8,7 +8,7 @@
struct iterator
{
int x;
- iterator(int v) :x(v) {}
+ explicit iterator(int v) :x(v) {}
iterator &operator ++() { ++x; return *this; }
int operator *() { return x; }
bool operator != (const iterator &o) { return x != o.x; }
@@ -36,7 +36,7 @@ namespace std
int main()
{
container c(1,4);
- for (iterator it : c)
+ for (int it : c)
{
}
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for9.C b/gcc/testsuite/g++.dg/cpp0x/range-for9.C
index 96e9cb61fd6..c51cbf99469 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for9.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for9.C
@@ -6,6 +6,6 @@
void test()
{
int a[] = {0,1,2};
- for (int x : a) // { dg-error "range-based-for" }
+ for (int x : a) // { dg-error "range-based 'for'" }
;
}