Bug #33268 Gcov offsets one line in sql_yacc.yy rules
Submitted: 16 Dec 2007 13:20 Modified: 31 Jan 2014 13:04
Reporter: Ingo Strüwing Email Updates:
Status: Won't fix Impact on me:
None 
Category:MySQL Server: Compiling Severity:S3 (Non-critical)
Version:5.1.23 OS:Linux (Debian x86_64)
Assigned to: CPU Architecture:Any

[16 Dec 2007 13:20] Ingo Strüwing
Description:
After a syntax change with new keywords, I found new keywords uncovered in the grammar rules "keyword:" and "keyword_sp:" (non-reserverd keywords). So I added test statements that cover these lines:

TEST SYNCHRONIZE NOW SIGNAL TEST;
TEST SYNCHRONIZE NOW SIGNAL CLEAR;

Here the token after SIGNAL can be identifier or string. I used the non-reserverd keywords TEST and CLEAR.

Now the DGcov output showed:

File: sql/sql_yacc.yy
-------------------------------------------------------------------------------
.    +++++:10259:        | SONAME_SYM            {}
.    +++++:10260:        | START_SYM             {}
.    +++++:10261:        | STOP_SYM              {}
|    #####:10262:        | TEST_SYM              {}
.        1:10263:        | TRUNCATE_SYM          {}
.    +++++:10264:        | UNICODE_SYM           {}
.    +++++:10265:        | UNINSTALL_SYM         {}

.    +++++:10297:        | CHAIN_SYM                {}
.    +++++:10298:        | CHANGED                  {}
.    +++++:10299:        | CIPHER_SYM               {}
|    #####:10300:        | CLEAR_SYM                {}
.        1:10301:        | CLIENT_SYM               {}
.    +++++:10302:        | COALESCE                 {}
.    +++++:10303:        | CODE_SYM                 {}

So it correctly noticed that the lines with TEST_SYM and CLEAR_SYM are new, but counted their use wrongly to one line below the new lines.

To find out how other places in sql_yacc.yy are counted, I added some non-sense code. The test result suggests that [D]Gcov  has an offset error for YACC rules, but not for embedded C code:

In the test file, the "test_sync_signal_wait test_sync_execute" rule was executed 55 times, the CLEAR rule 3 times, the "CLEAR TIMEOUT" rule never.

|        -:12411:          test_sync_signal_wait test_sync_execute
|        -:12412:          {
|       55:12413:            if (!Lex->test_sync_req.timeout)
|    #####:12414:              Lex->test_sync_req.timeout= 777;
|        -:12415:          }
|       55:12416:        | CLEAR_SYM
|        -:12417:          {

|        3:12418:            Lex->test_sync_req.activation_count= 0;
|        3:12419:            if (Lex->test_sync_req.activation_count)
|    #####:12420:              Lex->test_sync_req.activation_count= 0;
|        -:12421:          }
|        3:12422:        | CLEAR_SYM TIMEOUT_SYM
|        -:12423:          {
|    #####:12424:            Lex->test_sync_req.activation_count= 0;
|        -:12425:          }
|    #####:12426:        ;
|        -:12427:
|        -:12428:test_sync_signal_wait:
|        -:12429:          SIGNAL_SYM ident_or_text

You can see that the embedded C code lines have the expected counts, while in every case the next YACC rule takes the count that applies to its predecessor.

How to repeat:
See description.
[31 Jul 2008 16:53] Ingo Strüwing
The cause of the problem seems to be that bison (yacc) adds a line with "break;" to most executable blocks in sql_yacc.yy when it creates sql_yacc.cc.

For example these lines in sql_yqcc.yy

10569:        | HASH_SYM                 {}
10570:        | HIT_LIMIT_SYM            {}
10571:        | HOSTS_SYM                {}

become in sql_yacc.cc:

  case 1907:
#line 10569 "sql_yacc.yy"
    {}
    break;

  case 1908:
#line 10570 "sql_yacc.yy"
    {}
    break;

  case 1909:
#line 10571 "sql_yacc.yy"
    {}
    break;

This means that the break statements are accounted to the next line number in sql_yacc.yy by gcov.

It would be great if bison had an option to put the break statements on the same lines as the last line of each block.

Or if we had a tool that edits sql_yacc.cc after the bison run, at least when building for coverage testing.