Search code examples
c++static-analysisklocwork

Can Klocwork (or other tools) be aware of types, typedefs and #define directives?


I have been looking for tools to help detect errors that prevent a program from running properly as 64-bit code. Most recently, I've been toying with Klocwork and its custom checkers feature, which lets me navigate the source code as a tree using XPath. This is useful as a "smarter" alternative to regular expressions, but I have not been able to make it aware of types.

For example, let's say I'd like to find every instance of a for loop that uses either an int or a long to count. The following code is easy to find.

for (int i = 0; i < 10; i++)
    // ...

Searching for this code is trivial because the variable definition is right inside the loop. However, consider the following example.

int i;
// ...
for (i = 0; i < 10; i++)
    // ...

This is difficult to find because the variable definition is separate from the loop, and the necessary XPath expression would be either unwieldy or bug-prone.

So, can custom Klocwork rules find expressions like this where type-awareness is necessary, including resolving typedef and #define statements? Are there other tools which can do this?

EDIT 1: Consider the following example.

typedef int myint;

void Foo() {
    int i;
    for (i = 0; i < 10; i++) {
        Bar();
    }

    myint j;
    for (j = 0; j < 10; j++) {
        Bar();
    }
}

The solution provided by ahmeddirie finds the first loop because the type of i is explicitly defined as int. The second loop is not found, however, because the typedef has obscured the underlying type. What tools keep track of types in a way that would identify the second loop variable j as indeed being an int?


Solution

  • Not entirely sure if this is what you want, but you can always resolve types quite easily with built-in functions. For example, answering your question (although perhaps not your underlying need):

    //ForStmt / Init::ExprStmt / Expr::BinaryExpr [ $type := Left.getTypeName() ] [ $type = 'int' | $type.contains('long') ]
    

    This will find ‘for’ loops that use ‘int’ or ‘long int’ counter types quite handily, and can obviously be applied to any element of an expression-based statement.

    Type definitions are amenable to this kind of manipulation, whether programmer-defined or language-defined. Pre-processor definitions, however, will only yield their native language type (i.e. the macro itself isn’t available for manipulation via KAST, only what it expands to).