r194764 - [analyzer] Silence warnings coming from allocators used by std::basic_string.

Jordan Rose jordan_rose at apple.com
Thu Nov 14 18:11:19 PST 2013


Author: jrose
Date: Thu Nov 14 20:11:19 2013
New Revision: 194764

URL: http://llvm.org/viewvc/llvm-project?rev=194764&view=rev
Log:
[analyzer] Silence warnings coming from allocators used by std::basic_string.

This is similar to r194004: because we can't reason about the data structure
invariants of std::basic_string, the analyzer decides it's possible for an
allocator to be used to deallocate the string's inline storage. Just ignore
this by walking up the stack, skipping past methods in classes with
"allocator" in the name, and seeing if we reach std::basic_string that way.

PR17866

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

Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp?rev=194764&r1=194763&r2=194764&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp Thu Nov 14 20:11:19 2013
@@ -1549,18 +1549,32 @@ LikelyFalsePositiveSuppressionBRVisitor:
           return 0;
         }
       }
+
       // 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 (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+      const LocationContext *LCtx = N->getLocationContext();
+      do {
+        const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl());
+        if (!MD)
+          break;
+
         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);
     }
   }
 

Modified: cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h?rev=194764&r1=194763&r2=194764&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h (original)
+++ cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h Thu Nov 14 20:11:19 2013
@@ -118,7 +118,20 @@ namespace std {
   struct random_access_iterator_tag : public bidirectional_iterator_tag { };
 
   template <class _Tp>
-  class allocator {};
+  class allocator {
+  public:
+    void deallocate(void *p) {
+      ::delete p;
+    }
+  };
+
+  template <class _Alloc>
+  class allocator_traits {
+  public:
+    static void deallocate(void *p) {
+      _Alloc().deallocate(p);
+    }
+  };
 
   template <class _Tp, class _Alloc>
   class __list_imp
@@ -140,19 +153,28 @@ namespace std {
   };
 
   // basic_string
-  template<class _CharT>
+  template<class _CharT, class _Alloc = allocator<_CharT> >
   class __attribute__ ((__type_visibility__("default"))) basic_string {
+    _CharT localStorage[4];
+
+    typedef allocator_traits<_Alloc> __alloc_traits;
+
   public:
-    void push_back(int c);
+    void push_back(int c) {
+      // Fake error trigger.
+      // No warning is expected as we are suppressing warning comming
+      // out of std::basic_string.
+      int z = 0;
+      z = 5/z;
+    }
+
+    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);
+    }
   };
-  template <class _CharT>
-  void basic_string<_CharT>::push_back(int __c) {
-        // Fake error trigger.
-        // No warning is expected as we are suppressing warning comming
-        // out of std::basic_string.
-        int z = 0;
-        z = 5/z;
-  }
 }
 
 void* operator new(std::size_t, const std::nothrow_t&) throw();

Modified: cfe/trunk/test/Analysis/inlining/stl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/inlining/stl.cpp?rev=194764&r1=194763&r2=194764&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/inlining/stl.cpp (original)
+++ cfe/trunk/test/Analysis/inlining/stl.cpp Thu Nov 14 20:11:19 2013
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-container-inlining=true -analyzer-config c++-stdlib-inlining=false -verify %s
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-container-inlining=true -analyzer-config c++-stdlib-inlining=true -DINLINE=1 -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,cplusplus.NewDelete,debug.ExprInspection -analyzer-config c++-container-inlining=true -analyzer-config c++-stdlib-inlining=false -std=c++11 -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,cplusplus.NewDelete,debug.ExprInspection -analyzer-config c++-container-inlining=true -analyzer-config c++-stdlib-inlining=true -std=c++11 -DINLINE=1 -verify %s
 
 #include "../Inputs/system-header-simulator-cxx.h"
 
@@ -38,3 +38,7 @@ void testBasicStringSuppression() {
   v.push_back(1); // no-warning
 }
 
+void testBasicStringSuppression_append() {
+  std::basic_string<char32_t> v;
+  v += 'c'; // no-warning
+}





More information about the cfe-commits mailing list