[PATCH v2] [PR debug/67192] Fix C loops' back-jump location
Andreas Arnez
arnez@linux.vnet.ibm.com
Fri Oct 23 09:15:00 GMT 2015
After parsing an unconditional "while"- or "for"-loop, the C front-end
generates a backward-goto statement and implicitly sets its location to
the current input_location. But in some cases the parser peeks ahead
first, such that input_location already points to the line after the
loop and the generated backward-goto gets the wrong line number.
One way this can occur is with a loop body consisting of an "if"
statement, because then the parser peeks for an optional "else" before
finishing the loop.
Another way occurs since r223098 ("Implement -Wmisleading-indentation"),
even with a loop body enclosed in braces. This is because the check for
misleading indentation always peeks ahead one token as well.
This patch adds a new parameter to c_finish_loop that expclitly
specifies the location to be used for the loop iteration. All calls to
c_finish_loop are adjusted accordingly.
gcc/c/ChangeLog:
PR debug/67192
* c-typeck.c (c_finish_loop): Replace implicit use of
input_location by new parameter iter_locus.
* c-tree.h (c_finish_loop): Adjust prototype.
* c-array-notation.c (fix_builtin_array_notation_fn): Explicitly
pass input_location as the new parameter to c_finish_loop.
(build_array_notation_expr): Likewise.
(fix_conditional_array_notations_1): Likewise.
(fix_array_notation_expr): Likewise.
(fix_array_notation_call_expr): Likewise.
* c-parser.c (c_parser_while_statement): Choose iter_locus
depending on whether the loop body is enclosed in braces, and pass
it to c_finish_loop.
(c_parser_for_statement): Likewise.
(c_parser_do_statement): Use the final semicolon's location for
iter_locus and pass it to c_finish_loop.
gcc/testsuite/ChangeLog:
PR debug/67192
* gcc.dg/guality/pr67192.c: New test.
---
gcc/c/c-array-notation.c | 15 ++++---
gcc/c/c-parser.c | 13 ++++--
gcc/c/c-tree.h | 2 +-
gcc/c/c-typeck.c | 17 +++++---
gcc/testsuite/gcc.dg/guality/pr67192.c | 79 ++++++++++++++++++++++++++++++++++
5 files changed, 109 insertions(+), 17 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/guality/pr67192.c
diff --git a/gcc/c/c-array-notation.c b/gcc/c/c-array-notation.c
index 3de7569..c457eee2 100644
--- a/gcc/c/c-array-notation.c
+++ b/gcc/c/c-array-notation.c
@@ -591,7 +591,8 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
for (ii = 0; ii < rank; ii++)
{
tree new_loop = push_stmt_list ();
- c_finish_loop (location, an_loop_info[ii].cmp, an_loop_info[ii].incr,
+ c_finish_loop (location, input_location, an_loop_info[ii].cmp,
+ an_loop_info[ii].incr,
body, NULL_TREE, NULL_TREE, true);
body = pop_stmt_list (new_loop);
}
@@ -879,8 +880,8 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
append_to_statement_list_force (lhs_an_loop_info[ii].incr, &incr_list);
if (rhs_rank && rhs_an_loop_info[ii].incr)
append_to_statement_list_force (rhs_an_loop_info[ii].incr, &incr_list);
- c_finish_loop (location, cond_expr[ii], incr_list, body, NULL_TREE,
- NULL_TREE, true);
+ c_finish_loop (location, input_location, cond_expr[ii],
+ incr_list, body, NULL_TREE, NULL_TREE, true);
body = pop_stmt_list (new_loop);
}
append_to_statement_list_force (body, &loop_with_init);
@@ -1004,7 +1005,8 @@ fix_conditional_array_notations_1 (tree stmt)
{
tree new_loop = push_stmt_list ();
add_stmt (an_loop_info[ii].ind_init);
- c_finish_loop (location, an_loop_info[ii].cmp, an_loop_info[ii].incr,
+ c_finish_loop (location, input_location, an_loop_info[ii].cmp,
+ an_loop_info[ii].incr,
body, NULL_TREE, NULL_TREE, true);
body = pop_stmt_list (new_loop);
}
@@ -1107,7 +1109,7 @@ fix_array_notation_expr (location_t location, enum tree_code code,
{
tree new_loop = push_stmt_list ();
add_stmt (an_loop_info[ii].ind_init);
- c_finish_loop (location, an_loop_info[ii].cmp,
+ c_finish_loop (location, input_location, an_loop_info[ii].cmp,
an_loop_info[ii].incr, body, NULL_TREE,
NULL_TREE, true);
body = pop_stmt_list (new_loop);
@@ -1193,7 +1195,8 @@ fix_array_notation_call_expr (tree arg)
{
tree new_loop = push_stmt_list ();
add_stmt (an_loop_info[ii].ind_init);
- c_finish_loop (location, an_loop_info[ii].cmp, an_loop_info[ii].incr,
+ c_finish_loop (location, input_location, an_loop_info[ii].cmp,
+ an_loop_info[ii].incr,
body, NULL_TREE, NULL_TREE, true);
body = pop_stmt_list (new_loop);
}
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 704ebc6..69e0a9c 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -5438,13 +5438,16 @@ c_parser_while_statement (c_parser *parser, bool ivdep)
token_indent_info body_tinfo
= get_token_indent_info (c_parser_peek_token (parser));
+ bool is_braced = c_parser_next_token_is (parser, CPP_OPEN_BRACE);
body = c_parser_c99_block_statement (parser);
+ location_t iter_loc = is_braced ? input_location : loc;
token_indent_info next_tinfo
= get_token_indent_info (c_parser_peek_token (parser));
warn_for_misleading_indentation (while_tinfo, body_tinfo, next_tinfo);
- c_finish_loop (loc, cond, NULL, body, c_break_label, c_cont_label, true);
+ c_finish_loop (loc, iter_loc, cond, NULL, body, c_break_label,
+ c_cont_label, true);
add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
c_break_label = save_break;
c_cont_label = save_cont;
@@ -5490,7 +5493,8 @@ c_parser_do_statement (c_parser *parser, bool ivdep)
annot_expr_ivdep_kind));
if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
c_parser_skip_to_end_of_block_or_statement (parser);
- c_finish_loop (loc, cond, NULL, body, new_break, new_cont, false);
+ c_finish_loop (loc, input_location, cond, NULL, body, new_break,
+ new_cont, false);
add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
}
@@ -5727,7 +5731,9 @@ c_parser_for_statement (c_parser *parser, bool ivdep)
token_indent_info body_tinfo
= get_token_indent_info (c_parser_peek_token (parser));
+ bool is_braced = c_parser_next_token_is (parser, CPP_OPEN_BRACE);
body = c_parser_c99_block_statement (parser);
+ location_t iter_loc = is_braced ? input_location : loc;
token_indent_info next_tinfo
= get_token_indent_info (c_parser_peek_token (parser));
@@ -5736,7 +5742,8 @@ c_parser_for_statement (c_parser *parser, bool ivdep)
if (is_foreach_statement)
objc_finish_foreach_loop (loc, object_expression, collection_expression, body, c_break_label, c_cont_label);
else
- c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true);
+ c_finish_loop (loc, iter_loc, cond, incr, body, c_break_label,
+ c_cont_label, true);
add_stmt (c_end_compound_stmt (loc, block, flag_isoc99 || c_dialect_objc ()));
c_break_label = save_break;
c_cont_label = save_cont;
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index bee03d3..9c13672 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -630,7 +630,7 @@ extern int c_types_compatible_p (tree, tree);
extern tree c_begin_compound_stmt (bool);
extern tree c_end_compound_stmt (location_t, tree, bool);
extern void c_finish_if_stmt (location_t, tree, tree, tree, bool);
-extern void c_finish_loop (location_t, tree, tree, tree, tree, tree, bool);
+extern void c_finish_loop (location_t, location_t, tree, tree, tree, tree, tree, bool);
extern tree c_begin_stmt_expr (void);
extern tree c_finish_stmt_expr (location_t, tree);
extern tree c_process_expr_stmt (location_t, tree);
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index bc43602..e4b5471 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -9810,14 +9810,16 @@ c_finish_if_stmt (location_t if_locus, tree cond, tree then_block,
add_stmt (stmt);
}
-/* Emit a general-purpose loop construct. START_LOCUS is the location of
- the beginning of the loop. COND is the loop condition. COND_IS_FIRST
- is false for DO loops. INCR is the FOR increment expression. BODY is
- the statement controlled by the loop. BLAB is the break label. CLAB is
- the continue label. Everything is allowed to be NULL. */
+/* Emit a general-purpose loop construct. START_LOCUS is the location
+ of the beginning of the loop. ITER_LOCUS is the location of the
+ loop iteration. COND is the loop condition. COND_IS_FIRST is
+ false for DO loops. INCR is the FOR increment expression. BODY is
+ the statement controlled by the loop. BLAB is the break label.
+ CLAB is the continue label. Everything is allowed to be NULL. */
void
-c_finish_loop (location_t start_locus, tree cond, tree incr, tree body,
+c_finish_loop (location_t start_locus, location_t iter_locus,
+ tree cond, tree incr, tree body,
tree blab, tree clab, bool cond_is_first)
{
tree entry = NULL, exit = NULL, t;
@@ -9843,6 +9845,7 @@ c_finish_loop (location_t start_locus, tree cond, tree incr, tree body,
out of the loop, or to the top of it. If there's no exit condition,
then we just build a jump back to the top. */
exit = build_and_jump (&LABEL_EXPR_LABEL (top));
+ SET_EXPR_LOCATION (exit, iter_locus);
if (cond && !integer_nonzerop (cond))
{
@@ -9867,7 +9870,7 @@ c_finish_loop (location_t start_locus, tree cond, tree incr, tree body,
exit = fold_build3_loc (start_locus,
COND_EXPR, void_type_node, cond, exit, t);
else
- exit = fold_build3_loc (input_location,
+ exit = fold_build3_loc (iter_locus,
COND_EXPR, void_type_node, cond, exit, t);
}
diff --git a/gcc/testsuite/gcc.dg/guality/pr67192.c b/gcc/testsuite/gcc.dg/guality/pr67192.c
new file mode 100644
index 0000000..faef853
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/guality/pr67192.c
@@ -0,0 +1,79 @@
+/* PR debug/67192 */
+/* { dg-do run } */
+/* { dg-options "-g -Wmisleading-indentation" } */
+
+volatile int cnt = 0;
+
+__attribute__((noinline, noclone)) static int
+last (void)
+{
+ return ++cnt % 5 == 0;
+}
+
+__attribute__((noinline, noclone)) static void
+do_it (void)
+{
+ asm volatile ("" : : "r" (&cnt) : "memory");
+}
+
+__attribute__((noinline, noclone)) static void
+f1 (void)
+{
+ for (;; do_it())
+ if (last ())
+ break;
+ do_it (); /* { dg-final { gdb-test 25 "cnt" "5" } } */
+}
+
+__attribute__((noinline, noclone)) static void
+f2 (void)
+{
+ while (1)
+ if (last ())
+ break;
+ else
+ do_it ();
+ do_it (); /* { dg-final { gdb-test 36 "cnt" "10" } } */
+}
+
+__attribute__((noinline, noclone)) static void
+f3 (void)
+{
+ for (;; do_it())
+ {
+ if (last ())
+ break;
+ }
+ do_it (); /* { dg-final { gdb-test 47 "cnt" "15" } } */
+}
+
+__attribute__((noinline, noclone)) static void
+f4 (void)
+{
+ while (1)
+ {
+ if (last ())
+ break;
+ do_it ();
+ }
+ do_it (); /* { dg-final { gdb-test 59 "cnt" "20" } } */
+}
+
+void (*volatile fnp1) (void) = f1;
+void (*volatile fnp2) (void) = f2;
+void (*volatile fnp3) (void) = f3;
+void (*volatile fnp4) (void) = f4;
+
+int
+main ()
+{
+ asm volatile ("" : : "r" (&fnp1) : "memory");
+ asm volatile ("" : : "r" (&fnp2) : "memory");
+ asm volatile ("" : : "r" (&fnp3) : "memory");
+ asm volatile ("" : : "r" (&fnp4) : "memory");
+ fnp1 ();
+ fnp2 ();
+ fnp3 ();
+ fnp4 ();
+ return 0;
+}
--
2.3.0
More information about the Gcc-patches
mailing list