]> granicus.if.org Git - clang/commitdiff
[analyzer] Just silence all warnings coming out of std::basic_string.
authorJordan Rose <jordan_rose@apple.com>
Fri, 7 Feb 2014 17:35:04 +0000 (17:35 +0000)
committerJordan Rose <jordan_rose@apple.com>
Fri, 7 Feb 2014 17:35:04 +0000 (17:35 +0000)
This means always walking the whole call stack for the end path node, but
we'll assume that's always fairly tractable.

<rdar://problem/15952973>

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@200980 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
test/Analysis/Inputs/system-header-simulator-cxx.h
test/Analysis/inlining/stl.cpp

index c389efdbcbed374ca4292977515a726e0980d7b7..4c1edf5f747016b2cac32317edfe63438daeb23d 100644 (file)
@@ -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<CXXMethodDecl>(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);
+      }
     }
   }
 
index 82b50782cba061a8bf28e05c438ef97c4f5c4085..35869214ed7e8235212637740a6dde51e306e386 100644 (file)
@@ -155,11 +155,21 @@ namespace std {
   // basic_string
   template<class _CharT, class _Alloc = allocator<_CharT> >
   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]);
     }
   };
 }
index c153174d27ad7c013ad6cdee9f62352f5a497b03..711c30f1031dd21ca273c640188e8f31aea6ce2d 100644 (file)
@@ -42,3 +42,8 @@ void testBasicStringSuppression_append() {
   std::basic_string<char32_t> v;
   v += 'c'; // no-warning
 }
+
+void testBasicStringSuppression_assign(std::basic_string<char32_t> &v,
+                                       const std::basic_string<char32_t> &v2) {
+  v = v2;
+}