Our team is constantly enhancing the PVS-Studio static analyzer to boost the code analysis efficiency. In this article, we will explore the latest analyzer updates that significantly improve the analysis of Unreal Engine projects.
It all started when Epic Games, the Unreal Engine developers, reported a large number of false positives when using built-in macros:
struct AAA
{
virtual int aaa() { return 1; }
virtual void bbb() {}
};
static void ccc(AAA* ptr)
{
check(ptr);
int ddd = ptr->aaa();
if (ptr) // <= V595 The 'ptr' pointer was utilized before
// it was verified agains nullptr.
{
ptr->bbb();
}
}
It's expected that the ptr pointer will be non-null if the control flow moves to the next instruction after the pointer has been passed to the check macro. The analyzer had a different perspective here and issued false positives. Epic Games also stated that the issue occurred only when using the Shipping configuration.
The Shipping configuration is typically intended for a release build, but developers often use it during the development stage for the following purposes:
When we looked into the issue more closely, we discovered that the CA_ASSUME macro, which is located inside the check macro, was causing the false positive:
#define CA_ASSUME( Expr ) __analysis_assume( !!( Expr ) )
We've already mentioned that Shipping builds are similar to the Release ones. So, once preprocessed, the macro expands to the noop operation (i.e., it does nothing). It looks like this:
{
....
do
{
__noop(!!(ptr));
}
while ((0, 0) __pragma(warning(pop)));
};
Here's an interesting fact: Epic Games informed us that Clang Static Analyzer doesn't issue false positives for the pattern. This inspired us to look at the CA_ASSUME macro implementation for Clang Static Analyzer:
__declspec(dllimport, noreturn) void CA_AssumeNoReturn();
#define CA_ASSUME( Expr ) ( __builtin_expect(!bool(Expr), 0) \
? CA_AssumeNoReturn() \
: (void)0 )
The macro expands to a noreturn function call if the passed expression is false. This helps Clang Static Analyzer determine that the pointer after the macro call is non-null.
After discussing this with Epic Games, we decided to create our own implementation of the check macros to help the PVS-Studio analyzer work correctly. The feature will be available starting with the PVS-Studio 7.33 and Unreal Engine 5.5 releases.
We worked together with the Unreal Engine developers to change the intermediate format for warning output. Now the C and C++ analyzer core issues warnings in a new format. The support for multi-file navigation in the code is its main advantage for the user. If you are using the UnrealBuildTool integration to check your Unreal Engine projects, update the analyzer to version 7.30 (and above) to use this feature.
Now you can easily determine where exactly the null pointer was dereferenced and the path it took to get there.
SN-DBS is a distributed build system designed to significantly enhance compilation performance. This is done by distributing build tasks across multiple nodes, which is especially useful for large-scale projects.
When PVS-Studio tried to analyze a project built in SN-DBS, an issue arose: the tool analyzed only the files that were processed on the master node. The build logs contained an error message.
The fix for this issue is ready and is expected in the upcoming Unreal Engine 5.5 release.
You can integrate PVS-Studio into your build process by modifying the target file. This is particularly useful if you need to frequently regenerate project files.
To integrate PVS-Studio, add the 'StaticAnalyzer' parameter with the 'PVSStudio' value:
For version 5.0 and earlier:
WindowsPlatform.StaticAnalyzer = WindowsStaticAnalyzer.PVSStudio;
For version 5.1 and later:
StaticAnalyzer = StaticAnalyzer.PVSStudio;
In addition to the 'StaticAnalyzer' parameter, you can add other settings, which we'll talk about below.
Starting with Unreal Engine 5.4, the analysis of autogenerated files (that have the *.gen.cpp extension) is disabled by default. This was done to reduce the analysis time for large projects. You can revert to the old behavior using a special flag:
-StaticAnalyzerIncludeGenerated
Unreal Engine 5.4 introduced a setting that sets the level of warnings issued by UnrealBuildTool during the analysis. It doesn't affect the PVS-Studio work but may cause a slowdown when getting a report. This is due to the setting that is enabled by default. As a result, UnrealBuildTool issues more warnings than necessary, increasing the time it takes to generate and process the report.
To disable it and avoid the issue described above, add the following flag to the UnrealBuildTool command line:
-StaticAnalyzerPVSPrintLevel = 0
Otherwise, you can configure this setting in the *.Target.cs file:
StaticAnalyzerPVSPrintLevel = 0;
Starting with Unreal Engine 5.4, a setting to run the analyzer only for project files (skipping the Unreal Engine core module) has become available. It enables you to boost the analysis speed, especially if no changes have been made to the Unreal Engine source code.
To enable the setting, add the following flag to the UnrealBuildTool command line:
-StaticAnalyzerProjectOnly
Otherwise, you can configure this setting in the *.Target.cs file:
bStaticAnalyzerProjectOnly = true;
Users may experience increased memory consumption when analyzing Unreal Engine projects. There are two main reasons for this:
We've significantly optimized the analyzer performance (in terms of analysis time and memory consumption) and have made great progress there. However, we still recommend you to disable the analysis of unity packs when working with large projects. You can learn how to do this here.
PVS-Studio provides diagnostic rules for detecting bugs specific to Unreal Engine projects:
We've already received feedback from our users about false positives and have fixed some of them. We're currently fixing the remaining issues.
We also welcome any suggestions for new rules. You can learn more about it here.
Unreal Engine users have been experiencing a large number of false positives from the General Analysis diagnostic rules. In response, we've started addressing these issues. We've now fixed the diagnostic rules that were causing the most false positives in the Unreal Engine code:
We're not done yet! The team is currently enhancing the next set of diagnostic rules.
We hope that the enhancements described in this article will help both Epic Games developers and Unreal Engine users.
If you have ideas for analyzer enhancements or new diagnostic rules for Unreal Engine projects, please feel free to share them with us. We're always open to new suggestions.
Stay tuned for all the latest updates :)