aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorCasey Carter <casey@carter.net>2016-03-14 19:57:54 +0000
committerJason Merrill <jason@gcc.gnu.org>2016-03-14 15:57:54 -0400
commit598a208cc0442bf7109ee545fa82d6c0607b9adf (patch)
tree34ab5c82e313155f42a5d0b7684c3fda07a35970 /gcc
parent3cbf012a4007511b8989d90e9450a93d4c75a8a6 (diff)
downloadgcc-598a208cc0442bf7109ee545fa82d6c0607b9adf.zip
gcc-598a208cc0442bf7109ee545fa82d6c0607b9adf.tar.gz
gcc-598a208cc0442bf7109ee545fa82d6c0607b9adf.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/parser.c20
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/range-for1.C23
4 files changed, 49 insertions, 4 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 94e4427..1a668e8 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+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
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 6ae45b0..d38f1dd 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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;
}
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for5.C b/gcc/testsuite/g++.dg/cpp0x/range-for5.C
index bf04406..2a20db4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for5.C
@@ -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};
diff --git a/gcc/testsuite/g++.dg/cpp1z/range-for1.C b/gcc/testsuite/g++.dg/cpp1z/range-for1.C
new file mode 100644
index 0000000..370381a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/range-for1.C
@@ -0,0 +1,23 @@
+// 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 ();
+}