41

The Xcode 4 static analyzer reports in my code some false positives. Is there any way to suppress them?

DreamOfMirrors
  • 2,147
  • 1
  • 21
  • 34
  • 2
    A false positive is possible, though rare. Post your code, please. – bbum Apr 27 '11 at 15:04
  • Using Apple singleton design pattern (see [Creating a Singleton Instance](http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/CocoaObjects.html%23//apple_ref/doc/uid/TP40002974-CH4-SW32) of "Cocoa Fundamentals Guide" ) the analyzer gives a "Potential leak of an object allocated on line XX". – DreamOfMirrors Apr 27 '11 at 15:12
  • 5
    It could be argued that a design that relies on a singleton is deserving of a static analyser message. :-) – JeremyP Apr 27 '11 at 15:59
  • 9
    This is a well asked question. It is asking how to disable the warnings case-by-case, not how to design software or whether or not one should avoid singletons. Singletons are also not the only case where this happens with the analyzer. A "false positive" in this case is usually referring to a situation where the analyzer believes there is a potential memory leak, but the developer knows better because he/she can think more abstractly than the compiler. – quickthyme Jul 01 '11 at 17:32
  • Example: search for strcat and strcpy here: http://www.boost.org/doc/libs/1_56_0/boost/regex/v4/regex_workaround.hpp – GrumpyOldTroll Aug 29 '14 at 03:10
  • That is safe 3rd party code (length-checked wrappers for strcat and strcpy), and it's preventing me from building with warnings as errors because it's flagged in my compile with "/../../../3rdParty/boost/build_result/include/boost/regex/v4/regex_workaround.hpp:201:7: Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119" A "#pragma XAnalyzer ignore -W CWE-119" would be nice here, if it existed. Safer than editing my copy of boost, I think. – GrumpyOldTroll Aug 29 '14 at 03:22
  • I have a (false? not false? ) positive where I am given an object, and call setObject:forKey: for a slightly modified object. If I am given a nil object, that's a bug, so I just pass the nil object to setObject:forKey:. It will crash. I know that. That's what I want, I want a crash when the caller gives me an incorrect parameter. The static analyser figures it out and complains. – gnasher729 May 22 '15 at 16:50

4 Answers4

72

I found a solution: false positives (like the Apple singleton design pattern) can be avoided with:

#ifndef __clang_analyzer__

// Code not to be analyzed

#endif

Analyzer will not analyze the code between those preprocessor directives.

DreamOfMirrors
  • 2,147
  • 1
  • 21
  • 34
  • Will this make that code not compiled at all when analyzing? – CarmeloS Jul 29 '15 at 09:02
  • 1
    `__clang_analyzer__` is a macro, defined when the program is compiled for the analyzer (see the [Clang User's Manual](http://clang.llvm.org/docs/UsersManual.html#analyzer_diagnositics)). When it's defined, the code between `#ifndef` and `#endif` isn't being compiled, which means that the analyzer doesn't see it. However when the program is not compiled for the analyzer the macro is not defined and code is compiled as normal. – DreamOfMirrors Jul 29 '15 at 09:20
  • Something tells me, that it may not compile if you take out some part of code. Or you need a stub in #else. Am I right? – RavisMsk Jan 12 '16 at 11:27
  • This is a serious mistake - this preprocessor conditional, will make the "Code not to be analyzed" to also not be compiled at all when Analyzing the source - hence will make the analyzed code not functional!!! also, if for example within that #ifndef you declare a variable - all other code outside that #ifndef...#endif will not have that variable!!! – Motti Shneor Oct 11 '22 at 08:15
8

Take a look at this page which shows how to use several #defines to annotate objective-c methods and parameters to help the static analyzer (clang) do the right thing

http://clang-analyzer.llvm.org/annotations.html

From that page:

The Clang frontend supports several source-level annotations in the form of GCC-style attributes and pragmas that can help make using the Clang Static Analyzer more useful. These annotations can both help suppress false positives as well as enhance the analyzer's ability to find bugs.

Logachu
  • 559
  • 6
  • 13
  • 1
    These annotations seem like a better choice than `#ifndef __clang_analyzer__`, since they apply to methods wherever they're used. For example: `@property (nonatomic, retain) NSString* newString NS_RETURNS_NOT_RETAINED;` – Noah Harrison Nov 30 '12 at 21:18
6

See my answer here. You can add a compile flag to the files and static analyzer will ignore them. This is probably better for 3rd party code you aren't concerned about, and not for first party code you are writing.

Community
  • 1
  • 1
kcharwood
  • 2,501
  • 19
  • 22
0

most of the time, using things like CF_RETURNS_RETAINED and following the 'create' rule works for me, but I ran into a case I could NOT suppress. Finally found a way to suppress the analyzer by looking at llvm source code:

https://llvm.org/svn/llvm-project/cfe/trunk/test/ARCMT/objcmt-arc-cf-annotations.m.result

"Test to see if we suppress an error when we store the pointer to a global."

static CGLayerRef sSuppressStaticAnalyzer;
static CGLayerRef sDmxImg[2][2][1000]; // a cache of quartz drawings.
CGLayerRef CachedDmxImg(...) // which lives for lifetime of app!
{
    ...

    CGLayerRef img = sDmxImg[isDefault][leadingZeroes][dmxVal];
    if ( !img )
    {
        NSRect imgRect = <some cool rectangle>;

        [NSGraphicsContext saveGraphicsState];
        CGContextRef ctx = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
        CGLayerRef cgLayerRef = CGLayerCreateWithContext(ctx, imgRect.size, NULL);
        CGContextRef layerCtx = CGLayerGetContext(cgLayerRef);
        [NSGraphicsContext setCurrentContext: [NSGraphicsContext graphicsContextWithGraphicsPort:layerCtx flipped:YES]];

        ... draw some gorgeous expensive Quartz stuff ...

        img = cgLayerRef;
        sDmxImg[isDefault][leadingZeroes][dmxVal] = cgLayerRef;
        sSuppressStaticAnalyzer = cgLayerRef; // suppress static analyzer warning!
        [NSGraphicsContext restoreGraphicsState];
   }
   return img;
}

For some reason, assigning to a static array didn't suppress the warning, but assigning to a plain old static 'sSuppressStaticAnalyzer' does. By the way the above method, using CGLayerRef is the fastest way I've found to redraw cached images (besides OpenGL).

Keith Knauber
  • 752
  • 6
  • 13