Search code examples
c++c++11clang-static-analyzerfalse-positive

Is the clang static analyzer confused by popping the front from a list of unique_ptrs?


The following C++11 code is a minimal example of what I believe triggers a false positive in clang:

#include <iostream>
#include <list>
#include <memory>

class ElementType {};

int main(int argc, const char * argv[]) {
    std::list<std::unique_ptr<ElementType>> theList(5);

    theList.pop_front();

    for (const auto &element: theList) { // (*)
        std::cout << "This should be fine." << std::endl;
    }

    return 0;
}

On the line marked by an asterisk (*), the clang analyzer claims

...filePath.../main.cpp:21:29: Use of memory after it is freed (within a call to 'begin')

As far as I interpret it, this code is harmless, but clang misses the point that std::list<T>::pop_front() not only calls its elements' destructor, but that it also moves the location of std::list<T>::begin(). Replacing the call to pop_front by pop_back makes the analyzer warning disappear, and even replacing it by erase(theList.begin()) makes it come out warning-free.

Am I missing something or did I actually stumble upon a missed case in clang?

For reference: These results come from XCode 5.1.1 (5B1008) on Mac OS X 10.9.2,

$ clang --version
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.1.0
Thread model: posix

Solution

  • It has been acknowledged to be a bug by the LLVM team.

    In a comment on Revision 211832 it is stated that since

    [t]he analyzer cannot reason about the internal invariances of [containers such as std::vector and std::list] which leads to false positives

    the analyzer should

    just not inline the methods of the containers and allow objects to escape whenever such methods are called.

    The issue is indeed no longer reproducible on XCode 6.4 (6E35b) with

    $ clang --version
    Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
    Target: x86_64-apple-darwin14.4.0
    Thread model: posix