[Sanitizer] define InternalScopedBuffer to replace large arrays on stack. It is defined analogous to similar class in tsan and should replace it.

git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@162262 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h
index 4c7c1e9..c4b4a83 100644
--- a/lib/sanitizer_common/sanitizer_common.h
+++ b/lib/sanitizer_common/sanitizer_common.h
@@ -53,6 +53,30 @@
 // returns a pointer to the beginning of the block.
 void *InternalAllocBlock(void *p);
 
+// InternalScopedBuffer can be used instead of large stack arrays to
+// keep frame size low.
+template<typename T>
+class InternalScopedBuffer {
+ public:
+  explicit InternalScopedBuffer(uptr cnt) {
+    cnt_ = cnt;
+    ptr_ = (T*)InternalAlloc(cnt * sizeof(T));
+  }
+  ~InternalScopedBuffer() {
+    InternalFree(ptr_);
+  }
+  T &operator[](uptr i) { return ptr_[i]; }
+  T *data() { return ptr_; }
+  uptr size() { return cnt_ * sizeof(T); }
+
+ private:
+  T *ptr_;
+  uptr cnt_;
+  // Disallow evil constructors.
+  InternalScopedBuffer(const InternalScopedBuffer&);
+  void operator=(const InternalScopedBuffer&);
+};
+
 // IO
 void RawWrite(const char *buffer);
 void Printf(const char *format, ...);
diff --git a/lib/sanitizer_common/tests/sanitizer_allocator_test.cc b/lib/sanitizer_common/tests/sanitizer_allocator_test.cc
index d6c7f56..d3445b6 100644
--- a/lib/sanitizer_common/tests/sanitizer_allocator_test.cc
+++ b/lib/sanitizer_common/tests/sanitizer_allocator_test.cc
@@ -53,4 +53,18 @@
   }
 }
 
+TEST(Allocator, ScopedBuffer) {
+  const int kSize = 512;
+  {
+    InternalScopedBuffer<int> int_buf(kSize);
+    EXPECT_EQ(sizeof(int) * kSize, int_buf.size());  // NOLINT
+  }
+  InternalScopedBuffer<char> char_buf(kSize);
+  EXPECT_EQ(sizeof(char) * kSize, char_buf.size());  // NOLINT
+  memset(char_buf.data(), 'c', kSize);
+  for (int i = 0; i < kSize; i++) {
+    EXPECT_EQ('c', char_buf[i]);
+  }
+}
+
 }  // namespace __sanitizer