Can Klocwork (or other tools) know types, typedefs and #define directives?

I looked for tools to detect errors that interfere with the normal operation of the program, like 64-bit code. Most recently, I worked with Klocwork and its special checkers function, which allows me to navigate in the source code like a tree using XPath. This is useful as a β€œsmarter” alternative to regular expressions, but I couldn't find out about types.

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

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

Finding this code is trivial because the definition of a variable is right inside the loop. However, consider the following example.

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

This is hard to find because the definition of a variable is separate from the loop, and the required XPath expression will be either bulky or error prone.

So, can Klocwork custom rules find expressions like this when type understanding is required, including allowing typedef and #define statements? Are there other tools that 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 type i explicitly defined as int . The second loop was not found, however, since typedef closed the base type. What tools track types in such a way as to identify the second variable of cycle j , as in the case of int ?

+6
source share
3 answers

Not quite sure if this is what you want, but you can always easily resolve types with built-in functions. For example, answering your question (although perhaps not your basic 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 conveniently and, obviously, can be applied to any element of the expression based on the expression.

Type definitions lend themselves to this type of manipulation, regardless of whether the programmer is defined or the language is defined. However, the definitions in front of the processor will lead only to their native language (i.e. the macro itself is not accessible for manipulation via KAST, only that it extends).

+1
source

You can use Clang ( http://clang.llvm.org ) or even Elsa ( https://github.com/dsw/oink-stack/ ) to generate an AST after type propagation and template creation. Both provide a decent C ++ API and some means of dumping AST into readable text. And both options are free.

+2
source

The company I work with is Semantic Designs Inc. provides tools that include a common infrastructure for the analysis and transformation of programs and specific analysis components for various programming languages. Together they are known as DMS. In the case of C ++, DMS includes integrated lexers, preprocessors, parsers, the name and type of permission component for each of GCC3, GCC4, ISO14882c1998 (ANSI), Visual C ++ 6.0, and Unmanaged Visual Studio 2005 C ++. For various C dialects, there is also control flow analysis, side effects of the character analyzer and character dependency analyzer, with which tools such as a pointer, code deactivator, profiling function and slicer were implemented.

Name and type resolution components provide a complete table of information and search character characters, so identifier references can be easily associated with their types and other declarative information. The information is similar to what was captured and used by the compiler, but stored together with abstract syntax trees in a form suitable for adaptive reuse by any tool that includes a component.

Semantic Designs recently created its own tool that is specifically related to the types of index variables in the declaration loop, for example, in your example. In this case, the problem was to update the GCC2 code using the -fno-for-scope compiler switch, which provided a scope resolution rule for loop variables that was not supported in later GCC dialects. The tool was to convert the loops, moving the declarations of their loop variables to an external context that retained the -fno-for-scope scoping rule. Where such changes were not necessary, no changes were made.

Thus, the tool had to distinguish between the type associated with each reference to the loop variable, differentiating in the case of masking areas and recover the code to resolve the name GCC3 and GCC4 lead to the same semantic interpretation as GCC2 with -fno-for-sphere. This requires access to the symbol table information associated with each reference to the variables, and in the case where the code was moved, to restore the correct syntax for the type declaration for any variable whose declaration was moved. A table of references to symbol and identifier tables provided by DMS The C ++ name and type resolution component contains all the necessary information and the module for restoring the syntax of the prescribed type allowed us to synthesize the correct declarations of the new type.

For example, consider an example:

 // loop variable hides variable in global scope // will change meaning without -fno-for-scope // fix: move decl. of cnt before for-loop // optionally rename globcnt loop variable float globcnt = 0.0; int Foo::foo3() { for (int globcnt = 0; globcnt < 5; globcnt++) { globalInt += globcnt; } globalInt += 2*globcnt + 1; return 0; } 

GCC2 -fno-for-scope semantics indicates that references to globcnt outside of a loop are related to a loop variable, although GCC3 consider a loop variable outside of scope and allow references to a global variable. The tool converted this code to:

 float globcnt = 0.0; int Foo::foo3() { int globcnt = 0; for (; globcnt < 5; globcnt++) { globalInt += globcnt; } globalInt += 2*globcnt + 1; return 0; } 

If the code had not been converted, GCC4 would always return the value 1 from Foo: foo3. However, the converted value would have been exposed to the loop iterations that were originally developed for Gcc2. The tool had to recognize that the final reference to globcnt was a local variable of type int, and not a global variable of type float, which it could perform by searching the symbol table and act accordingly.

On the other hand, the tool is recognized in the following code, which had no references to me outside the loop, so it was acceptable (and preferable) to leave the declaration of the loop variable unchanged.

 int Foo::foo0() { for (int i = 0; i < 10; i++) { globalInt += i*i; } return 0; } 
+1
source

Source: https://habr.com/ru/post/891138/


All Articles