From: Jordan Rose Date: Fri, 7 Feb 2014 17:35:04 +0000 (+0000) Subject: [analyzer] Just silence all warnings coming out of std::basic_string. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cbf51ddf2a3aab307b0972000b91b174712c0fa8;p=clang [analyzer] Just silence all warnings coming out of std::basic_string. This means always walking the whole call stack for the end path node, but we'll assume that's always fairly tractable. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@200980 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index c389efdbcb..4c1edf5f74 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -1558,25 +1558,18 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC, // std::u16string s; s += u'a'; // because we cannot reason about the internal invariants of the // datastructure. - const LocationContext *LCtx = N->getLocationContext(); - do { + for (const LocationContext *LCtx = N->getLocationContext(); LCtx; + LCtx = LCtx->getParent()) { const CXXMethodDecl *MD = dyn_cast(LCtx->getDecl()); if (!MD) - break; + continue; const CXXRecordDecl *CD = MD->getParent(); if (CD->getName() == "basic_string") { BR.markInvalid(getTag(), 0); return 0; - } else if (CD->getName().find("allocator") == StringRef::npos) { - // Only keep searching if the current method is in a class with the - // word "allocator" in its name, e.g. std::allocator or - // allocator_traits. - break; } - - LCtx = LCtx->getParent(); - } while (LCtx); + } } } diff --git a/test/Analysis/Inputs/system-header-simulator-cxx.h b/test/Analysis/Inputs/system-header-simulator-cxx.h index 82b50782cb..35869214ed 100644 --- a/test/Analysis/Inputs/system-header-simulator-cxx.h +++ b/test/Analysis/Inputs/system-header-simulator-cxx.h @@ -155,11 +155,21 @@ namespace std { // basic_string template > class __attribute__ ((__type_visibility__("default"))) basic_string { - _CharT localStorage[4]; + bool isLong; + union { + _CharT localStorage[4]; + _CharT *externalStorage; + + void assignExternal(_CharT *newExternal) { + externalStorage = newExternal; + } + } storage; typedef allocator_traits<_Alloc> __alloc_traits; public: + basic_string(); + void push_back(int c) { // Fake error trigger. // No warning is expected as we are suppressing warning coming @@ -168,11 +178,24 @@ namespace std { z = 5/z; } + _CharT *getBuffer() { + return isLong ? storage.externalStorage : storage.localStorage; + } + basic_string &operator +=(int c) { // Fake deallocate stack-based storage. // No warning is expected as we are suppressing warnings within - // allocators being used by std::basic_string. - __alloc_traits::deallocate(&localStorage); + // std::basic_string. + __alloc_traits::deallocate(getBuffer()); + } + + basic_string &operator =(const basic_string &other) { + // Fake deallocate stack-based storage, then use the variable in the + // same union. + // No warning is expected as we are suppressing warnings within + // std::basic_string. + __alloc_traits::deallocate(getBuffer()); + storage.assignExternal(new _CharT[4]); } }; } diff --git a/test/Analysis/inlining/stl.cpp b/test/Analysis/inlining/stl.cpp index c153174d27..711c30f103 100644 --- a/test/Analysis/inlining/stl.cpp +++ b/test/Analysis/inlining/stl.cpp @@ -42,3 +42,8 @@ void testBasicStringSuppression_append() { std::basic_string v; v += 'c'; // no-warning } + +void testBasicStringSuppression_assign(std::basic_string &v, + const std::basic_string &v2) { + v = v2; +}