Menu

Why multiCondition?

2019-08-30
2019-08-30
  • Sander Bouwhuis

    Sander Bouwhuis - 2019-08-30

    I have many constructions like this in my code:

     1 case WM_COMMAND: // 0x111
     2   // What command message was sent?
     3   switch(HIWORD(wParam))
     4   {
     5     case CBN_SELENDOK: // 0x09
     6       // The user changed the selection of a combo box
     7       if(HWND(lParam) == m_hComboDsn)
     8         OnSelectDsn();
     9       else if(HWND(lParam) == m_hComboSite)
    10         OnSelectSite();
    11       else if(HWND(lParam) == m_hComboMember)
    12         OnSelectMember();
    13       else
    14         return DefWindowProc(hWnd, u32Msg, wParam, lParam);
    15       break;
    16
    17     default:
    18       return DefWindowProc(hWnd, u32Msg, wParam, lParam);
    19   }
    20   break;
    

    Everytime I get errors stating 'multiCondition':
    line 9 : 'Expression is always false because 'else if' condition matches previous condition at line 7.
    line 11 : 'Expression is always false because 'else if' condition matches previous condition at line 7.

    In this case there are only 2 'else if' constructions, but if there are more I get errors for all of them.
    Obviously, m_hComboDsn and m_hComboSite and m_hComboMember are different HWND handles.

    Why is this error thrown?

     

    Last edit: Sander Bouwhuis 2019-08-30
  • versat

    versat - 2019-08-30

    When usíng --platform=win64 i can reproduce these messages.
    In the Cppcheck windows library configuration HWND is configured as a void pointer.
    According to the debug output Cppcheck sees something like this:

    if ( void * ( lParam ) == m_hComboDsn ) {
      OnSelectDsn ( ) ; }
    else { if ( void * ( lParam ) == m_hComboSite ) {
      OnSelectSite ( ) ; }
    else { if ( void * ( lParam ) == m_hComboMember ) {
      OnSelectMember ( ) ; }
    

    I remember that i have created a ticket regarding these functional cast expressions some time ago: https://trac.cppcheck.net/ticket/8969
    Maybe they still do not always work as they should.
    If i surround the HWNDwith brackets (like this: if((HWND)(lParam) == m_hComboDsn) there are no strange warnings any longer.
    I will try to create a useful ticket for this.

     
  • versat

    versat - 2019-08-30

    I have created a ticket for this: https://trac.cppcheck.net/ticket/9307
    Thanks for reporting

     
  • Sander Bouwhuis

    Sander Bouwhuis - 2019-08-30

    So it has to do with the difference between a cast and a constructor?
    cast : (HWND)lParam
    constructor : HWND(lParam)

    I always use the second notation, because almost all classes have a bunch of constructors, but not many classes have explicit cast functions.

     
  • versat

    versat - 2019-08-30

    As far as i see it is not a constructor, it is just another kind of cast.
    HWND is no class or struct as far as i know, so there is no constructor.
    Looking into the Cppcheck code with Visual Studio it shows me that HWND is defined via

    DECLARE_HANDLE            (HWND);
    

    DECLARE_HANDLE is defined in the following way:

    #define DECLARE_HANDLE(name) struct name##__{int unused;}; typedef struct name##__ *name
    

    This expands to:

    struct HWND__{int unused;}; typedef struct HWND__ *HWND;
    

    So HWND is a pointer to a struct. Thus it has no constructor.
    The Cppcheck configuration that tells Cppcheck that HWND is a void * is not completely wrong i would say. It should be useful for the analysis.
    The issue is with the functional cast expression vs. a C-style cast expression.

     

Log in to post a comment.