c++lintpc-lint

Expected an expression error, found 'WIN32'


I have following C++ code and running PC lint on code.

Question 1:

#if !WIN32
#define ULONG_MAX 0xffffffff
#endif

Above code is throwing an lint error as follows

Error 26: Expected an expression, found 'WIN32'
Error 30: Expected an integer constant

How to fix above error?

Question 2:

const char CompanyName[] = "mycompany"; 

Error: Note 960: Violates MISRA Required Rule 8.5, no object/function definitions in header files

How to fix above error?

Question 3:

unsigned long m_ClientThreadId; 
m_ClientThreadId        = 0;

Note 960: Violates MISRA Required Rule 10.1, Implicit conversion changes signedness

How to fix above error?


Solution

  • Several points need clarification. For example, the line:

    #if !WIN32
    

    is actually well defined by the standard, and could be reasonably used if your compiler invocations always containt /DWIN32=1 or -DWIN32=0. For that matter, the standard says that symbols which aren't defined are replaced by 0 during macro expansion, so there is never any problem with the line, unless some other convention states that the symbol will only be defined on Windows machines, but the value it is defined to isn't specified; in that case, you need something like:

    #ifndef WIN32
    

    In the end, it depends on the conventions you've established for handling compiler dependencies.

    On the other hand, the line which immediately follows should be avoided, since it defines a symbol (ULONG_MAX) which is defined in the C and C++ standards. The three line sequence here should be replaced by:

    #include <limits.h>
    

    With regards to the second question, I'm not sure if the error isn't a miss-interpretation of the MISRA rule. In C++, const implies internal linkage by default: defining the symbol like this in a header will cause multiple instantiations of the variable (with a different address in each translation unit), but will not cause problems with multiple definitions. And the alternatives also have their disadvantages. My preference here would be to replace the variable definition with a macro:

    #define CompanyName "mycompany"
    

    but macros have their own problems. Declaring the symbol extern, and then defining it in one (and only one) source file is another alternative, but this involves two statements, in two different files, where (depending on the role the variable plays), one might be preferable. (Judging by the name, I don't think the two statements would be an issue, but there are other cases where it is preferable to keep the text visible in the header.) Leaving it as you've written it is also a viable alternative, unless your company has strict rules against it.

    With regards to the last point, the expression 0 has type int, which is signed. You can clearly specify the type, 0UL, but frankly, this shouldn't be necessary: 0 is 0, regardless of the type, and while there may be cases where you want to force the type, to ensure that arithmetic takes place in a certain way, this isn't one of them. As for the error/warning, I suspect that this is also a mis-interpretation of the MISRA rules; implicit conversions which change signedness can be problematic, but not when what is being converted is a very small non-negative constant integer. So write 0UL if you need to to adhere to company rules, but do realize that this is carrying things to the point of silliness: a case of a basically sound rule being applied in cases where it isn't relevant.