[llvm-bugs] [Bug 37459] New: Static analyzer temp-dtor-inlining doesn't appear to escape by-value function parameters

via llvm-bugs llvm-bugs at lists.llvm.org
Mon May 14 12:44:15 PDT 2018


https://bugs.llvm.org/show_bug.cgi?id=37459

            Bug ID: 37459
           Summary: Static analyzer temp-dtor-inlining doesn't appear to
                    escape by-value function parameters
           Product: clang
           Version: trunk
          Hardware: PC
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: Static Analyzer
          Assignee: dcoughlin at apple.com
          Reporter: george.burgess.iv at gmail.com
                CC: llvm-bugs at lists.llvm.org

It looks like the analyzer assumes that, given

void foo(std::unique_ptr<int> i);

void bar() {
  auto x = std::make_unique<int>();
  int *i = x.get();
  foo(std::move(x));
  *i = 99;
}

...`i` is always freed after the call to `foo` completes, so the store to *i is
broken. However, if we change `foo` to take a `std::unique_ptr<int> &&`, the
analyzer assumes that it can't know what happened to `x` during the call, and
doesn't warn.

Since the unique_ptr passed to `foo` can be stashed away in a global, class
member, etc. I think the analyzer should be more conservative with code like
the above.

Test-case:

$ cat /tmp/sa-test.cpp
// Stripped down unique_ptr<int>
struct IntPtr {
  IntPtr(): i(new int) {}
  IntPtr(IntPtr &&o): i(o.i) { o.i = nullptr; }
  ~IntPtr() { delete i; }

  int *i;
};

struct Foo {
  Foo(IntPtr);
  void bar();

  IntPtr i;
};

void bar() {
  IntPtr ptr;
  int *i = ptr.i;
  Foo f(static_cast<IntPtr &&>(ptr));
  *i = 99;
  f.bar();
}

$ clang-tidy /tmp/sa-test.cpp -- -Xclang -analyzer-config -Xclang
'c++-temp-dtor-inlining=false' -std=c++11

$ clang-tidy /tmp/sa-test.cpp -- -std=c++11
1 warning generated.
/tmp/sa-test.cpp:20:6: warning: Use of memory after it is freed
[clang-analyzer-cplusplus.NewDelete]
  *i = 99;
     ^
/tmp/sa-test.cpp:17:10: note: Calling default constructor for 'IntPtr'
  IntPtr ptr;
         ^
/tmp/sa-test.cpp:2:15: note: Memory is allocated
  IntPtr(): i(new int) {}
              ^
/tmp/sa-test.cpp:17:10: note: Returning from default constructor for 'IntPtr'
  IntPtr ptr;
         ^
/tmp/sa-test.cpp:19:35: note: Calling '~IntPtr'
  Foo f(static_cast<IntPtr &&>(ptr));
                                  ^
/tmp/sa-test.cpp:4:15: note: Memory is released
  ~IntPtr() { delete i; }
              ^
/tmp/sa-test.cpp:19:35: note: Returning from '~IntPtr'
  Foo f(static_cast<IntPtr &&>(ptr));
                                  ^
/tmp/sa-test.cpp:20:6: note: Use of memory after it is freed
  *i = 99;
     ^

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20180514/0026bba7/attachment.html>


More information about the llvm-bugs mailing list