diff options
author | Marek Polacek <polacek@redhat.com> | 2018-09-07 14:12:48 +0000 |
---|---|---|
committer | Marek Polacek <mpolacek@gcc.gnu.org> | 2018-09-07 14:12:48 +0000 |
commit | 8112667c8cb2fe109bc169561d68277277d35dc8 (patch) | |
tree | d8b5de955e6ab86691eb6cf20cdd7c9733cf9009 /gcc/cp | |
parent | 6bf9284fbfe4f37cdb02c502b211dd28317710a6 (diff) | |
download | gcc-8112667c8cb2fe109bc169561d68277277d35dc8.zip gcc-8112667c8cb2fe109bc169561d68277277d35dc8.tar.gz gcc-8112667c8cb2fe109bc169561d68277277d35dc8.tar.bz2 |
PR c++/87152 - range-based for loops with initializer broken in templates.
* constexpr.c (potential_constant_expression_1) <case RANGE_FOR_STMT>:
Recur into RANGE_FOR_INIT_STMT.
* cp-tree.def: Add RANGE_FOR_INIT_STMT to RANGE_FOR_STMT.
* cp-tree.h (RANGE_FOR_INIT_STMT): Define.
* dump.c (cp_dump_tree) <case RANGE_FOR_STMT>: Also dump
RANGE_FOR_INIT_STMT.
* pt.c (tsubst_expr) <case RANGE_FOR_STMT>: Recur into
RANGE_FOR_INIT_STMT.
* semantics.c (begin_range_for_stmt): Adjust call to build_stmt.
Do put the init statement in RANGE_FOR_INIT_STMT.
(finish_range_for_decl): Pop it for templates.
* g++.dg/cpp2a/range-for11.C: New test.
* g++.dg/cpp2a/range-for12.C: New test.
* g++.dg/cpp2a/range-for13.C: New test.
* g++.dg/cpp2a/range-for14.C: New test.
* g++.dg/cpp2a/range-for15.C: New test.
* g++.dg/cpp2a/range-for16.C: New test.
* g++.dg/cpp2a/range-for17.C: New test.
* g++.dg/cpp2a/range-for18.C: New test.
* g++.dg/parse/error61.C (foo): Adjust dg-error.
From-SVN: r264158
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 2 | ||||
-rw-r--r-- | gcc/cp/cp-tree.def | 7 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/dump.c | 1 | ||||
-rw-r--r-- | gcc/cp/pt.c | 1 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 15 |
7 files changed, 32 insertions, 10 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 42e70cd..70c462c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,18 @@ +2018-09-07 Marek Polacek <polacek@redhat.com> + + PR c++/87152 - range-based for loops with initializer broken in templates. + * constexpr.c (potential_constant_expression_1) <case RANGE_FOR_STMT>: + Recur into RANGE_FOR_INIT_STMT. + * cp-tree.def: Add RANGE_FOR_INIT_STMT to RANGE_FOR_STMT. + * cp-tree.h (RANGE_FOR_INIT_STMT): Define. + * dump.c (cp_dump_tree) <case RANGE_FOR_STMT>: Also dump + RANGE_FOR_INIT_STMT. + * pt.c (tsubst_expr) <case RANGE_FOR_STMT>: Recur into + RANGE_FOR_INIT_STMT. + * semantics.c (begin_range_for_stmt): Adjust call to build_stmt. + Do put the init statement in RANGE_FOR_INIT_STMT. + (finish_range_for_decl): Pop it for templates. + 2018-09-06 Bernd Edlinger <bernd.edlinger@hotmail.de> * decl.c (check_initializer): Call cp_complete_array_type. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index f646519..6c26890 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -5767,6 +5767,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, return true; case RANGE_FOR_STMT: + if (!RECUR (RANGE_FOR_INIT_STMT (t), any)) + return false; if (!RECUR (RANGE_FOR_EXPR (t), any)) return false; if (!RECUR (RANGE_FOR_BODY (t), any)) diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 1b0326f..c64225d 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -301,9 +301,10 @@ DEFTREECODE (IF_STMT, "if_stmt", tcc_statement, 4) DEFTREECODE (FOR_STMT, "for_stmt", tcc_statement, 5) /* Used to represent a range-based `for' statement. The operands are - RANGE_FOR_DECL, RANGE_FOR_EXPR, RANGE_FOR_BODY, and RANGE_FOR_SCOPE, - RANGE_FOR_UNROLL respectively. Only used in templates. */ -DEFTREECODE (RANGE_FOR_STMT, "range_for_stmt", tcc_statement, 5) + RANGE_FOR_DECL, RANGE_FOR_EXPR, RANGE_FOR_BODY, RANGE_FOR_SCOPE, + RANGE_FOR_UNROLL, and RANGE_FOR_INIT_STMT, respectively. Only used in + templates. */ +DEFTREECODE (RANGE_FOR_STMT, "range_for_stmt", tcc_statement, 6) /* Used to represent a 'while' statement. The operands are WHILE_COND and WHILE_BODY, respectively. */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index df441fc..b78e9eb 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4923,6 +4923,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) #define RANGE_FOR_BODY(NODE) TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 2) #define RANGE_FOR_SCOPE(NODE) TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 3) #define RANGE_FOR_UNROLL(NODE) TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 4) +#define RANGE_FOR_INIT_STMT(NODE) TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 5) #define RANGE_FOR_IVDEP(NODE) TREE_LANG_FLAG_6 (RANGE_FOR_STMT_CHECK (NODE)) #define SWITCH_STMT_COND(NODE) TREE_OPERAND (SWITCH_STMT_CHECK (NODE), 0) diff --git a/gcc/cp/dump.c b/gcc/cp/dump.c index 9c1e5fc..d9b868b 100644 --- a/gcc/cp/dump.c +++ b/gcc/cp/dump.c @@ -301,6 +301,7 @@ cp_dump_tree (void* dump_info, tree t) case RANGE_FOR_STMT: dump_stmt (di, t); + dump_child ("init", RANGE_FOR_INIT_STMT (t)); dump_child ("decl", RANGE_FOR_DECL (t)); dump_child ("expr", RANGE_FOR_EXPR (t)); dump_child ("body", RANGE_FOR_BODY (t)); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 0a618a5..892a387 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -16815,6 +16815,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, stmt = (processing_template_decl ? begin_range_for_stmt (NULL_TREE, NULL_TREE) : begin_for_stmt (NULL_TREE, NULL_TREE)); + RECUR (RANGE_FOR_INIT_STMT (t)); decl = RANGE_FOR_DECL (t); decl = tsubst (decl, args, complain, in_decl); maybe_push_decl (decl); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 676de01..f3e5d83 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1101,8 +1101,8 @@ begin_range_for_stmt (tree scope, tree init) { begin_maybe_infinite_loop (boolean_false_node); - tree r = build_stmt (input_location, RANGE_FOR_STMT, - NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE); + tree r = build_stmt (input_location, RANGE_FOR_STMT, NULL_TREE, NULL_TREE, + NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE); if (scope == NULL_TREE) { @@ -1110,22 +1110,23 @@ begin_range_for_stmt (tree scope, tree init) scope = begin_for_scope (&init); } - /* RANGE_FOR_STMTs do not use nor save the init tree, so we - pop it now. */ - if (init) - pop_stmt_list (init); + /* Since C++20, RANGE_FOR_STMTs can use the init tree, so save it. */ + RANGE_FOR_INIT_STMT (r) = init; RANGE_FOR_SCOPE (r) = scope; return r; } /* Finish the head of a range-based for statement, which may - be given by RANGE_FOR_STMT. DECL must be the declaration + be given by RANGE_FOR_STMT. DECL must be the declaration and EXPR must be the loop expression. */ void finish_range_for_decl (tree range_for_stmt, tree decl, tree expr) { + if (processing_template_decl) + RANGE_FOR_INIT_STMT (range_for_stmt) + = pop_stmt_list (RANGE_FOR_INIT_STMT (range_for_stmt)); RANGE_FOR_DECL (range_for_stmt) = decl; RANGE_FOR_EXPR (range_for_stmt) = expr; add_stmt (range_for_stmt); |