This article explores how the baseline approach streamlines static analyzer integration and discusses effective strategies for handling false positives.
Introducing the analyzer into a project with the baseline approach
A common challenge when introducing a static analyzer into an existing project is that this process rarely occurs at the "groundwork stage." That's why the analyzer floods users with warnings for the legacy code after the first run. For large codebases, warnings can quickly become overwhelming:
Now, imagine tackling all these warnings straight away—fixing errors and annotating each one. Not only would this consume significant time, but it might also drive developers crazy!
So, what's the solution?
A key point is that static analyzers require configuration before use. PVS-Studio, for example, offers over 1500 diagnostic rules across four languages. Naturally, not all diagnostic rules will suit your needs.
Let's take MISRA standards for C/C++ as an example. Our analyzer supports these standards with specific diagnostic rules. MISRA prioritizes safety and security, flagging even minor code issues—a necessity born from automotive software development but now critical in any high-stakes domain. If your code doesn't adhere to MISRA, its diagnostic rules will only add noise to your reports.
Note. If you are interested in MISRA standards, don't hesitate to explore our MISRA support page for details.
With the basics covered, let's address the core topic. Frenetically annotating and fixing every warning straight away isn't practical. Static analysis isn't introduced in a vacuum: the existing project code likely functions reliably.
Instead, we can treat the project state at integration time as a baseline and suppress all current warnings. This doesn't mean we shelve them: we're just putting them aside as technical debt to gradually fix them later. New post-integration warnings now become our immediate priority.
PVS-Studio static analyzer provides a suppression mode for such cases when the analyzer saves suppressed messages in so-called suppress files. This mode doesn't require altering source code—ideal for mass suppression. The analyzer records each warning's signature (including source context), preventing unnoticed reappearances in future reports.
How to suppress analyzer warnings? In the PVS-Studio's Visual Studio plugin, a dedicated button in the report viewer suppresses all warnings at once:
After clicking, PVS-Studio writes all warnings to the project's primary suppress file, removing them from the report view.
We can also suppress individual warnings via a dropdown menu:
This functionality exists across all PVS-Studio IDE plugins: IntelliJ IDEA, CLion, Rider, Visual Studio, VS Code, and Qt Creator.
In Visual Studio, the Suppress Messages menu tracks suppressed warnings:
Note. Learn how to suppress warnings in IDE plugins and other integrations in the documentation section.
Suppressing false positives
False positives are another common case for suppression. Keep in mind that static analyzers rely on a probabilistic approach. Therefore, the analyzer can be wrong, too.
Note. Sometimes, excluding specific files is wiser than fighting false positives. The analyzer may issue various warnings, for example, for auto-generated files. By removing them, we will make the report much less noisy.
To suppress a false positive in PVS-Studio, use special comments. Suppose the analyzer issues a warning for this snippet:
size_t n = 100;
for (unsigned i = 0;
i < n; // here we get V104
i++)
{
// ...
}
If we're confident this warning is erroneous and it should be removed from the report, add a comment with a diagnostic rule number:
size_t n = 100;
for (unsigned i = 0;
i < n; //-V104
i++)
{
// ...
}
Suppressing multiple diagnostic rules on one line is equally straightforward:
struct Small { int *pointer; };
struct Big { int *array[20]; };
int Add(const Small &a, Big b) //-V835 //-V813
{
return *a.pointer + *b.array[10];
}
Optionally, we can add a hash code to the False Alarm mark. If we change the line with this hash code, the analyzer warnings won't be marked as false positive, as the hash code of the changed line will be different.
To enable this function, add the following flag to the.pvsconfig
configuration file:
//V_ENABLE_FALSE_ALARMS_WITH_HASH
In the code, the mark with the hash code looks as follows:
//-V817 //-VH"3652460326"
Note. See this documentation section to find out more about this mode and advanced diagnostic configuration.
Suppressing macro-related warnings is trickier. The analyzer is triggered wherever the macro is used—where its body is substituted into the code.
#define TEST_MACRO \
int a = 0; \
size_t b = 0; \
b = a;
void func1()
{
TEST_MACRO // V1001 triggers here
}
void func2()
{
TEST_MACRO // V1001 also triggers here
}
In this case, we can use a special markup to inform the analyzer that all instances of this macro should be treated as a false positive:
//-V:TEST_MACRO:1001
#define TEST_MACRO \
int a = 0; \
size_t b = 0; \
b = a;
void func1()
{
TEST_MACRO
}
void func2()
{
TEST_MACRO
}
We can also simply remove these warnings. To do this, we can leave the following comment:
//-V::1001:TEST_MACRO
....
As in the previous example, we can specify several diagnostic rules for macros at once:
//-V:TEST_MACRO:1001, 105, 201
Manually adding comments isn't always convenient. PVS-Studio IDE plugins simplify this: click Mark selected messages as False Alarms in the context menu.
After this, the false positive comment inserts automatically:
To revisit warnings marked as false positive, enable the DisplayFalseAlarms option to include them in the analyzer report.
All PVS-Studio IDE plugins support mass suppression and false positive markup.
Note. Read more about these and other methods of dealing with false positives in this documentation section.
Don't hesitate to report false positives to our support team! Analyzer quality matters to us, so we actively fix valid cases. Contact us via the website feedback form.
Disabling diagnostic rules for a code snippet
In some cases, we need to disable diagnostic rules for a code block—not for the entire project. PVS-Studio for C/C++ supports #pragma directives for this:
-
#pragma pvs(push)
saves current diagnostic rule's enable/disable settings; -
#pragma pvs(disable: XXXX, YYYY, ...)
disables listed diagnostic rules; -
#pragma pvs(enable: XXXX, YYYY, ...)
enables listed diagnostic rules; -
#pragma pvs(pop)
restores previous settings.
Look at the example:
void func(int* p1, int* p2)
{
if (!p1 || !p2)
return;
#pragma pvs(push)
#pragma pvs(disable: 547)
if (p1) // V547 will not be issued
do_something();
#pragma pvs(pop)
if (p2) // V547 Expression 'p2' is always true.
do_other();
}
To prevent warnings about unknown #pragma
, pass the flag to the compiler:
- GCC/Clang:
-Wno-unknown-pragmas
- MSVC:
-wd4068
Conclusion
We've explored how to integrate static analysis into legacy projects seamlessly using the baseline approach—ignoring legacy warnings to focus on new ones. We've also discussed that the analyzer is not perfect and can issue false positive warnings, but PVS-Studio provides convenient ways both for mass and individual warning suppression.
If uncertain about adopting static analysis, you're welcome to test PVS-Studio on your code with a free license. Thanks for reading! And let me end this post by rewording a proverb: "Trying once beats hearing or reading a hundred times."
Top comments (0)