﻿# Interprocedural context\-sensitive analysis

Static code analyzers can take into consideration the data exchanged between procedures/functions, helping to detect more errors and [potential vulnerabilities](https://pvs-studio.com/en/blog/terms/6441/)\. This is crucial for identifying issues like memory leaks, null pointer dereferences, and array overruns, as these errors often arise when resource creation, usage, and release are handled by different functions\.

To detect errors that result from the interaction of multiple functions, static analyzers use interprocedural context\-sensitive code analysis\.

We'll explore it in detail by examining a real error that PVS\-Studio [detected](https://pvs-studio.com/en/blog/posts/csharp/0966/) in the AvalonStudio source code \(C\#\)\.

Let's look at the _IsBuiltInType_ function first\. Note that if its parameter, _cursor_, turns to be a null reference, the function returns _false_\.

```cpp
private static bool IsBuiltInType(ClangType cursor)
{
  var result = false;
  if (cursor != null && ....)
  {
    return true;
  }
  return result;
}
```

Take a look at another code fragment where the above function is called:

```cpp
private static StyledText InfoTextFromCursor(ClangCursor cursor)
{
  ....
  if (cursor.ResultType != null)
  {
    result.Append(cursor.ResultType.Spelling + " ",
                  IsBuiltInType(cursor.ResultType) ? theme.Keyword 
                                                   : theme.Type);
  }
  else if (cursor.CursorType != null)
  {
    switch (kind)
    {
      ....
    }
    result.Append(cursor.CursorType.Spelling + " ",
                  IsBuiltInType(cursor.ResultType) ? theme.Keyword
                                                   : theme.Type);
  }
  ....
}
```

If _cursor\.ResultType \!\= null_, the body of the first _if_ statement is executed\. So, if control is passed inside the body of the second _if_, statement, we know for sure that _cursor\.ResultType_ reference is null\.

Let's examine the spot where the _IsBuiltInType_ function \(which we discussed earlier\) is called:

```cpp
result.Append(cursor.CursorType.Spelling + " ",
              IsBuiltInType(cursor.ResultType) ? theme.Keyword
                                               : theme.Type);
```

The analyzer recognizes that _cursor\.ResultType_ is a null reference\. So, it concludes that with this argument, **the function always returns** _**false**_\.

That's what the interprocedural context\-sensitive analysis is all about\.

The ternary operator condition that is always false seems suspicious, so the analyzer issues a warning:

[V3022](https://pvs-studio.com/en/docs/warnings/v3022/) Expression 'IsBuiltInType\(cursor\.ResultType\)' is always false\.

The analyzer is right\. If we examine the code more closely, we'll notice a typo\. In the body of the second _if_ statement, the _cursor\.CursorType_ variable should be passed as the argument when calling the _IsBuiltInType_ function\.

The fixed code:

```cpp
private static StyledText InfoTextFromCursor(ClangCursor cursor)
{
  ....
  if (cursor.ResultType != null)
  {
    result.Append(cursor.ResultType.Spelling + " ",
                  IsBuiltInType(cursor.ResultType) ? theme.Keyword 
                                                   : theme.Type);
  }
  else if (cursor.CursorType != null)
  {
    switch (kind)
    {
      ....
    }
    result.Append(cursor.CursorType.Spelling + " ",
                  IsBuiltInType(cursor.CursorType) ? theme.Keyword
                                                   : theme.Type);
  }
  ....
}
```

Analyzing the interaction of functions located in different translation units or program modules adds complexity\. In this case, it is referred to as intermodular analysis\.

**Additional links**

1. [Static code analysis](https://pvs-studio.com/en/blog/terms/0046/)\.
1. Andrey Karpov\. [How static analysis works](https://pvs-studio.com/en/blog/posts/1048/)?
1. Andrey Karpov\. [What static analysis cannot find](https://pvs-studio.com/en/blog/posts/1037/)\.