dcoughlin created this revision. dcoughlin added reviewers: zaks.anna, NoQ. dcoughlin added a subscriber: cfe-commits. Herald added a subscriber: aemerson.
The analyzer does not model C++ temporary destructors completely and so reports false alarms about leaks of memory allocated by the internals of shared_ptr: std::shared_ptr<int> p(new int(1)); p = nullptr; // 'Potential leak of memory pointed to by field __cntrl_' To avoid these spurious diagnostics, this patch suppresses all diagnostics where the end of the path is inside a method in std::shared_ptr. rdar://problem/23652766 http://reviews.llvm.org/D22048 Files: lib/StaticAnalyzer/Core/BugReporterVisitors.cpp test/Analysis/Inputs/system-header-simulator-cxx.h test/Analysis/inlining/stl.cpp Index: test/Analysis/inlining/stl.cpp =================================================================== --- test/Analysis/inlining/stl.cpp +++ test/Analysis/inlining/stl.cpp @@ -52,3 +52,9 @@ void testSupprerssion_independent_bits_engine(MyEngine& e) { std::__independent_bits_engine<MyEngine, unsigned int> x(e, 64); // no-warning } + +void testSuppression_std_shared_pointer() { + std::shared_ptr<int> p(new int(1)); + + p = nullptr; // no-warning +} Index: test/Analysis/Inputs/system-header-simulator-cxx.h =================================================================== --- test/Analysis/Inputs/system-header-simulator-cxx.h +++ test/Analysis/Inputs/system-header-simulator-cxx.h @@ -329,6 +329,36 @@ z = 5/z; } +#if __has_feature(cxx_decltype) +typedef decltype(nullptr) nullptr_t; + +template<class _Tp> +class shared_ptr +{ +public: + constexpr shared_ptr(nullptr_t); + explicit shared_ptr(_Tp* __p); + + shared_ptr(shared_ptr&& __r) { } + + ~shared_ptr(); + + shared_ptr& operator=(shared_ptr&& __r) { + // Fake error trigger. + // No warning is expected as we are suppressing warning coming + // out of std::basic_string. + int z = 0; + z = 5/z; + } +}; + +template<class _Tp> +inline +constexpr +shared_ptr<_Tp>::shared_ptr(nullptr_t) { +} + +#endif // __has_feature(cxx_decltype) } void* operator new(std::size_t, const std::nothrow_t&) throw(); Index: lib/StaticAnalyzer/Core/BugReporterVisitors.cpp =================================================================== --- lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -1596,23 +1596,31 @@ } } - // The analyzer issues a false positive on - // std::basic_string<uint8_t> v; v.push_back(1); - // and - // std::u16string s; s += u'a'; - // because we cannot reason about the internal invariants of the - // datastructure. for (const LocationContext *LCtx = N->getLocationContext(); LCtx; LCtx = LCtx->getParent()) { const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl()); if (!MD) continue; const CXXRecordDecl *CD = MD->getParent(); + // The analyzer issues a false positive on + // std::basic_string<uint8_t> v; v.push_back(1); + // and + // std::u16string s; s += u'a'; + // because we cannot reason about the internal invariants of the + // datastructure. if (CD->getName() == "basic_string") { BR.markInvalid(getTag(), nullptr); return nullptr; } + + // The analyzer issues a false positive on + // std::shared_ptr<int> p(new int(1)); p = nullptr; + // because it does not reason properly about temporary destructors. + if (CD->getName() == "shared_ptr") { + BR.markInvalid(getTag(), nullptr); + return nullptr; + } } } }
Index: test/Analysis/inlining/stl.cpp =================================================================== --- test/Analysis/inlining/stl.cpp +++ test/Analysis/inlining/stl.cpp @@ -52,3 +52,9 @@ void testSupprerssion_independent_bits_engine(MyEngine& e) { std::__independent_bits_engine<MyEngine, unsigned int> x(e, 64); // no-warning } + +void testSuppression_std_shared_pointer() { + std::shared_ptr<int> p(new int(1)); + + p = nullptr; // no-warning +} Index: test/Analysis/Inputs/system-header-simulator-cxx.h =================================================================== --- test/Analysis/Inputs/system-header-simulator-cxx.h +++ test/Analysis/Inputs/system-header-simulator-cxx.h @@ -329,6 +329,36 @@ z = 5/z; } +#if __has_feature(cxx_decltype) +typedef decltype(nullptr) nullptr_t; + +template<class _Tp> +class shared_ptr +{ +public: + constexpr shared_ptr(nullptr_t); + explicit shared_ptr(_Tp* __p); + + shared_ptr(shared_ptr&& __r) { } + + ~shared_ptr(); + + shared_ptr& operator=(shared_ptr&& __r) { + // Fake error trigger. + // No warning is expected as we are suppressing warning coming + // out of std::basic_string. + int z = 0; + z = 5/z; + } +}; + +template<class _Tp> +inline +constexpr +shared_ptr<_Tp>::shared_ptr(nullptr_t) { +} + +#endif // __has_feature(cxx_decltype) } void* operator new(std::size_t, const std::nothrow_t&) throw(); Index: lib/StaticAnalyzer/Core/BugReporterVisitors.cpp =================================================================== --- lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -1596,23 +1596,31 @@ } } - // The analyzer issues a false positive on - // std::basic_string<uint8_t> v; v.push_back(1); - // and - // std::u16string s; s += u'a'; - // because we cannot reason about the internal invariants of the - // datastructure. for (const LocationContext *LCtx = N->getLocationContext(); LCtx; LCtx = LCtx->getParent()) { const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl()); if (!MD) continue; const CXXRecordDecl *CD = MD->getParent(); + // The analyzer issues a false positive on + // std::basic_string<uint8_t> v; v.push_back(1); + // and + // std::u16string s; s += u'a'; + // because we cannot reason about the internal invariants of the + // datastructure. if (CD->getName() == "basic_string") { BR.markInvalid(getTag(), nullptr); return nullptr; } + + // The analyzer issues a false positive on + // std::shared_ptr<int> p(new int(1)); p = nullptr; + // because it does not reason properly about temporary destructors. + if (CD->getName() == "shared_ptr") { + BR.markInvalid(getTag(), nullptr); + return nullptr; + } } } }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits