c++ - Different branch coverage generated by GCC/GCOV for function using throw() / noexcept -


i understand branches generated gcc compiler when using noexcept or throw() marking non-throwing function. know differences between noexcept , throw(), cannot figure out additional branches defined when using throw() instead of noexcept , how improve coverage have 100% of branch coverage?

code snippet of tested example class:

class myclass { public:     myclass() noexcept :         ithrowflag(false)     {}      void non_throwing_method() noexcept     {         try         {             throwing_method();         }         catch (...)         {         }     }      void throwing_method()     {         if (ithrowflag)         {             throw std::exception();         }     }  public:     bool ithrowflag; }; 

there 2 test cases defined, both passing:

  1. verification if non_throwing_method completes when underlying throwing_method not throwing,
  2. verification if non_throwing_method completes when underlying throwing_method throwing exception.

below coverage report generated gcc/gcov above code, lines , branches covered (4/4 branches covered):

        -:    0:source:myclass.hh         -:    0:graph:main.gcno         -:    0:data:main.gcda         -:    0:runs:1         -:    0:programs:1         -:    1:#include <iostream>         -:    2:#include <string>         -:    3:         -:    4:using namespace std;         -:    5:         -:    6:class myclass         -:    7:{         -:    8:public: function _zn7myclassc2ev called 2 returned 100% blocks executed 100%         2:    9:    myclass() noexcept :         2:   10:        ithrowflag(false)         2:   11:    {}         -:   12: function _zn7myclass19non_throwing_methodev called 2 returned 100% blocks executed 100%         2:   13:    void non_throwing_method() noexcept         -:   14:    {         -:   15:        try         -:   16:        {         2:   17:            throwing_method(); call    0 returned 100% branch  1 taken 50% (fallthrough) branch  2 taken 50% (throw)         -:   18:        }         1:   19:        catch (...) call    0 returned 100%         -:   20:        {         -:   21:        }         2:   22:    }         -:   23: function _zn7myclass15throwing_methodev called 2 returned 50% blocks executed 100%         2:   24:    void throwing_method()         -:   25:    {         2:   26:        if (ithrowflag) branch  0 taken 50% (fallthrough) branch  1 taken 50%         -:   27:        {         1:   28:            throw std::exception(); call    0 returned 100% call    1 returned 100% call    2 returned 0%         -:   29:        }         1:   30:    }         -:   31:         -:   32:public:         -:   33:    bool ithrowflag;         -:   34:}; 

as target platform not support c++11 , noexcept, exchanged throw() specifier below:

class myclass { public:     myclass() throw() :         ithrowflag(false)     {}      void non_throwing_method() throw()     {         try         {             throwing_method();         }         catch (...)         {         }     }      void throwing_method()     {         if (ithrowflag)         {             throw std::exception();         }     }  public:     bool ithrowflag; }; 

below gcov output examined branches (5/8). code throw() generates additional 4 branches, quite hard understand , cover testing:

        -:    0:source:myclass.hh         -:    0:graph:main.gcno         -:    0:data:main.gcda         -:    0:runs:1         -:    0:programs:1         -:    1:#include <iostream>         -:    2:#include <string>         -:    3:         -:    4:using namespace std;         -:    5:         -:    6:class myclass         -:    7:{         -:    8:public: function _zn7myclassc2ev called 2 returned 100% blocks executed 100%         2:    9:    myclass() throw() :         2:   10:        ithrowflag(false)         2:   11:    {}         -:   12: function _zn7myclass19non_throwing_methodev called 2 returned 100% blocks executed 75%         2:   13:    void non_throwing_method() throw()         -:   14:    {         -:   15:        try         -:   16:        {         2:   17:            throwing_method(); call    0 returned 100% branch  1 taken 50% (fallthrough) branch  2 taken 50% (throw)         -:   18:        }         1:   19:        catch (...) call    0 returned 100% call    1 returned 100% branch  2 taken 100% (fallthrough) branch  3 taken 0% (throw) branch  4 never executed branch  5 never executed call    6 never executed         -:   20:        {         -:   21:        }         2:   22:    }         -:   23: function _zn7myclass15throwing_methodev called 2 returned 50% blocks executed 100%         2:   24:    void throwing_method()         -:   25:    {         2:   26:        if (ithrowflag) branch  0 taken 50% (fallthrough) branch  1 taken 50%         -:   27:        {         1:   28:            throw std::exception(); call    0 returned 100% call    1 returned 100% call    2 returned 0%         -:   29:        }         1:   30:    }         -:   31:         -:   32:public:         -:   33:    bool ithrowflag;         -:   34:}; 

test cases below (to have full details case):

void test1() {     myclass lobj;     lobj.non_throwing_method(); }  void test2() {     myclass lobj;     lobj.ithrowflag = true;     lobj.non_throwing_method();     lobj.ithrowflag = false; } 

i appreciate if have answer/explanation described behavior.

edit: additionally attached assembly code (only code of function: `non_throwing_method1 compare).

with noexcept:

_zn7myclass19non_throwing_methodev: .lfb1253:     .loc 2 13 0     .cfi_startproc     .cfi_personality 0x3,__gxx_personality_v0     .cfi_lsda 0x3,.llsda1253     pushq   %rbp     .cfi_def_cfa_offset 16     .cfi_offset 6, -16     movq    %rsp, %rbp     .cfi_def_cfa_register 6     subq    $16, %rsp     movq    %rdi, -8(%rbp)     movq    __gcov0._zn7myclass19non_throwing_methodev(%rip), %rax     addq    $1, %rax     movq    %rax, __gcov0._zn7myclass19non_throwing_methodev(%rip)     .loc 2 17 0     movq    -8(%rbp), %rax     movq    %rax, %rdi .lehb0:     call    _zn7myclass15throwing_methodev .lehe0:     movq    __gcov0._zn7myclass19non_throwing_methodev+8(%rip), %rax     addq    $1, %rax     movq    %rax, __gcov0._zn7myclass19non_throwing_methodev+8(%rip)     .loc 2 22 0     jmp .l7 .l6:     movq    %rax, %rdx     movq    __gcov0._zn7myclass19non_throwing_methodev+16(%rip), %rax     addq    $1, %rax     movq    %rax, __gcov0._zn7myclass19non_throwing_methodev+16(%rip)     .loc 2 19 0     movq    %rdx, %rax     movq    %rax, %rdi     call    __cxa_begin_catch     movq    __gcov0._zn7myclass19non_throwing_methodev+24(%rip), %rax     addq    $1, %rax     movq    %rax, __gcov0._zn7myclass19non_throwing_methodev+24(%rip)     call    __cxa_end_catch     movq    __gcov0._zn7myclass19non_throwing_methodev+32(%rip), %rax     addq    $1, %rax     movq    %rax, __gcov0._zn7myclass19non_throwing_methodev+32(%rip) .l7:     .loc 2 22 0     nop     leave     .cfi_def_cfa 7, 8     ret     .cfi_endproc .lfe1253:     .globl  __gxx_personality_v0     .section    .gcc_except_table._zn7myclass19non_throwing_methodev,"ag",@progbits,_zn7myclass19non_throwing_methodev,comdat     .align 4 .llsda1253:     .byte   0xff     .byte   0x3     .uleb128 .llsdatt1253-.llsdattd1253 .llsdattd1253:     .byte   0x1     .uleb128 .llsdacse1253-.llsdacsb1253 .llsdacsb1253:     .uleb128 .lehb0-.lfb1253     .uleb128 .lehe0-.lehb0     .uleb128 .l6-.lfb1253     .uleb128 0x1 .llsdacse1253:     .byte   0x1     .byte   0     .align 4     .long   0  .llsdatt1253:     .section    .text._zn7myclass19non_throwing_methodev,"axg",@progbits,_zn7myclass19non_throwing_methodev,comdat     .size   _zn7myclass19non_throwing_methodev, .-_zn7myclass19non_throwing_methodev     .section    .text._zn7myclass15throwing_methodev,"axg",@progbits,_zn7myclass15throwing_methodev,comdat     .align 2     .weak   _zn7myclass15throwing_methodev     .type   _zn7myclass15throwing_methodev, @function 

with throw():

_zn7myclass19non_throwing_methodev: .lfb1253:     .loc 2 13 0     .cfi_startproc     .cfi_personality 0x3,__gxx_personality_v0     .cfi_lsda 0x3,.llsda1253     pushq   %rbp     .cfi_def_cfa_offset 16     .cfi_offset 6, -16     movq    %rsp, %rbp     .cfi_def_cfa_register 6     subq    $16, %rsp     movq    %rdi, -8(%rbp)     movq    __gcov0._zn7myclass19non_throwing_methodev(%rip), %rax     addq    $1, %rax     movq    %rax, __gcov0._zn7myclass19non_throwing_methodev(%rip)     .loc 2 17 0     movq    -8(%rbp), %rax     movq    %rax, %rdi .lehb0:     call    _zn7myclass15throwing_methodev .lehe0:     movq    __gcov0._zn7myclass19non_throwing_methodev+8(%rip), %rax     addq    $1, %rax     movq    %rax, __gcov0._zn7myclass19non_throwing_methodev+8(%rip)     .loc 2 22 0     jmp .l3 .l8:     movq    %rax, %rdx     movq    __gcov0._zn7myclass19non_throwing_methodev+16(%rip), %rax     addq    $1, %rax     movq    %rax, __gcov0._zn7myclass19non_throwing_methodev+16(%rip)     .loc 2 19 0     movq    %rdx, %rax     movq    %rax, %rdi     call    __cxa_begin_catch     movq    __gcov0._zn7myclass19non_throwing_methodev+24(%rip), %rax     addq    $1, %rax     movq    %rax, __gcov0._zn7myclass19non_throwing_methodev+24(%rip) .lehb1:     call    __cxa_end_catch .lehe1:     movq    __gcov0._zn7myclass19non_throwing_methodev+32(%rip), %rax     addq    $1, %rax     movq    %rax, __gcov0._zn7myclass19non_throwing_methodev+32(%rip)     .loc 2 22 0     jmp .l3 .l9:     cmpq    $-1, %rdx     je  .l7     movq    __gcov0._zn7myclass19non_throwing_methodev+48(%rip), %rdx     addq    $1, %rdx     movq    %rdx, __gcov0._zn7myclass19non_throwing_methodev+48(%rip)     movq    %rax, %rdi .lehb2:     call    _unwind_resume .l7:     movq    __gcov0._zn7myclass19non_throwing_methodev+40(%rip), %rdx     addq    $1, %rdx     movq    %rdx, __gcov0._zn7myclass19non_throwing_methodev+40(%rip)     .loc 2 13 0     movq    %rax, %rdi     call    __cxa_call_unexpected .lehe2: .l3:     .loc 2 22 0     leave     .cfi_def_cfa 7, 8     ret     .cfi_endproc .lfe1253:     .globl  __gxx_personality_v0     .section    .gcc_except_table._zn7myclass19non_throwing_methodev,"ag",@progbits,_zn7myclass19non_throwing_methodev,comdat     .align 4 .llsda1253:     .byte   0xff     .byte   0x3     .uleb128 .llsdatt1253-.llsdattd1253 .llsdattd1253:     .byte   0x1     .uleb128 .llsdacse1253-.llsdacsb1253 .llsdacsb1253:     .uleb128 .lehb0-.lfb1253     .uleb128 .lehe0-.lehb0     .uleb128 .l8-.lfb1253     .uleb128 0x1     .uleb128 .lehb1-.lfb1253     .uleb128 .lehe1-.lehb1     .uleb128 .l9-.lfb1253     .uleb128 0x3     .uleb128 .lehb2-.lfb1253     .uleb128 .lehe2-.lehb2     .uleb128 0     .uleb128 0 .llsdacse1253:     .byte   0x1     .byte   0     .byte   0x7f     .byte   0     .align 4     .long   0  .llsdatt1253:     .byte   0     .section    .text._zn7myclass19non_throwing_methodev,"axg",@progbits,_zn7myclass19non_throwing_methodev,comdat     .size   _zn7myclass19non_throwing_methodev, .-_zn7myclass19non_throwing_methodev     .section    .text._zn7myclass15throwing_methodev,"axg",@progbits,_zn7myclass15throwing_methodev,comdat     .align 2     .weak   _zn7myclass15throwing_methodev     .type   _zn7myclass15throwing_methodev, @function 


Comments

Popular posts from this blog

Command prompt result in label. Python 2.7 -

javascript - How do I use URL parameters to change link href on page? -

amazon web services - AWS Route53 Trying To Get Site To Resolve To www -