For case like belowi test.c:

1:int foo(char c)
2:{
3:  return ((c >= 'A' && c <= 'Z')
4:       || (c >= 'a' && c <= 'z')
5:       || (c >= '0' && c <='0'));}

the generated line number is incorrect for condition c>='A' of block 2:
Thus correct the condition op0 location.

gcno diff before and with this patch:

test.gcno:  575:                  block 11: 1:0001(tree)
test.gcno:  583:    01450000:  35:LINES
-test.gcno:  595:                  block 2:`test.c':1, 5
+test.gcno:  595:                  block 2:`test.c':1, 3
test.gcno:  626:    01450000:  31:LINES
test.gcno:  638:                  block 3:`test.c':3
test.gcno:  665:    01450000:  31:LINES
test.gcno:  677:                  block 4:`test.c':4
test.gcno:  704:    01450000:  31:LINES
test.gcno:  716:                  block 5:`test.c':4
test.gcno:  743:    01450000:  31:LINES
test.gcno:  755:                  block 6:`test.c':5

Also save line id in line vector for gcov debug use.

Regression tested pass on x86_64-linux-gnu and aarch64-linux-gnu, OK for
master?

gcc/ChangeLog:

        PR gcov/97923
        * gcov.cc (line_info::line_info): Init id.
        (solve_flow_graph): Fix typo.
        (add_line_counts): Set line->id.
        * gimplify.cc (shortcut_cond_r): Correct cond expr op0 location.

gcc/testsuite/ChangeLog:

        PR gcov/97923
        * gcc.misc-tests/gcov-pr97923.c: New test.

Signed-off-by: Xionghu Luo <xionghu...@tencent.com>
---
 gcc/gcov.cc                                 |  9 ++++++---
 gcc/gimplify.cc                             |  6 ++++--
 gcc/testsuite/gcc.misc-tests/gcov-pr97923.c | 13 +++++++++++++
 3 files changed, 23 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.misc-tests/gcov-pr97923.c

diff --git a/gcc/gcov.cc b/gcc/gcov.cc
index 2ec7248cc0e..77ca94c71c4 100644
--- a/gcc/gcov.cc
+++ b/gcc/gcov.cc
@@ -205,6 +205,8 @@ public:
   /* Execution count.  */
   gcov_type count;
 
+  unsigned id;
+
   /* Branches from blocks that end on this line.  */
   vector<arc_info *> branches;
 
@@ -216,8 +218,8 @@ public:
   unsigned has_unexecuted_block : 1;
 };
 
-line_info::line_info (): count (0), branches (), blocks (), exists (false),
-  unexceptional (0), has_unexecuted_block (0)
+line_info::line_info (): count (0), id (0), branches (), blocks (),
+  exists (false), unexceptional (0), has_unexecuted_block (0)
 {
 }
 
@@ -2370,7 +2372,7 @@ solve_flow_graph (function_info *fn)
 
   /* If the graph has been correctly solved, every block will have a
      valid count.  */
-  for (unsigned i = 0; ix < fn->blocks.size (); i++)
+  for (unsigned i = 0; i < fn->blocks.size (); i++)
     if (!fn->blocks[i].count_valid)
       {
        fnotice (stderr, "%s:graph is unsolvable for '%s'\n",
@@ -2730,6 +2732,7 @@ add_line_counts (coverage_info *coverage, function_info 
*fn)
                    }
                  line->count += block->count;
                }
+             line->id = ln;
            }
 
          has_any_line = true;
diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index ade6e335da7..341a27b033e 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -3915,7 +3915,8 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree 
*false_label_p,
        false_label_p = &local_label;
 
       /* Keep the original source location on the first 'if'.  */
-      t = shortcut_cond_r (TREE_OPERAND (pred, 0), NULL, false_label_p, locus);
+      tree op0 = TREE_OPERAND (pred, 0);
+      t = shortcut_cond_r (op0, NULL, false_label_p, EXPR_LOCATION (op0));
       append_to_statement_list (t, &expr);
 
       /* Set the source location of the && on the second 'if'.  */
@@ -3938,7 +3939,8 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree 
*false_label_p,
        true_label_p = &local_label;
 
       /* Keep the original source location on the first 'if'.  */
-      t = shortcut_cond_r (TREE_OPERAND (pred, 0), true_label_p, NULL, locus);
+      tree op0 = TREE_OPERAND (pred, 0);
+      t = shortcut_cond_r (op0, true_label_p, NULL, EXPR_LOCATION (op0));
       append_to_statement_list (t, &expr);
 
       /* Set the source location of the || on the second 'if'.  */
diff --git a/gcc/testsuite/gcc.misc-tests/gcov-pr97923.c 
b/gcc/testsuite/gcc.misc-tests/gcov-pr97923.c
new file mode 100644
index 00000000000..ad4f7d40817
--- /dev/null
+++ b/gcc/testsuite/gcc.misc-tests/gcov-pr97923.c
@@ -0,0 +1,13 @@
+/* { dg-options "-fprofile-arcs -ftest-coverage" } */
+/* { dg-do run { target native } } */
+
+int foo(int c)
+{
+  return ((c >= 'A' && c <= 'Z') /* count(1*) */
+      || (c >= 'a' && c <= 'z') /* count(1*) */
+      || (c >= '0' && c <= '0')); /* count(1*) */
+}
+
+int main() { foo(0); }
+
+/* { dg-final { run-gcov gcov-pr97923-1.c } } */
-- 
2.27.0

Reply via email to