[PATCH] D51317: Keep BumpPtrAllocator::Allocate(0) from returning nullptr

Brent Royal-Gordon via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 27 12:12:44 PDT 2018


brentdax created this revision.
brentdax added reviewers: hans, jordan_rose.
Herald added a subscriber: llvm-commits.

If a newly-allocated BumpPtrAllocator was asked for a zero-byte allocation, it would return nullptr in violation of its LLVM_ATTRIBUTE_RETURNS_NONNULL attribute. This change instead makes it return a valid but read-only address.


Repository:
  rL LLVM

https://reviews.llvm.org/D51317

Files:
  include/llvm/Support/Allocator.h
  unittests/Support/AllocatorTest.cpp


Index: unittests/Support/AllocatorTest.cpp
===================================================================
--- unittests/Support/AllocatorTest.cpp
+++ unittests/Support/AllocatorTest.cpp
@@ -185,4 +185,19 @@
   EXPECT_GT(MockSlabAllocator::GetLastSlabSize(), 4096u);
 }
 
+// Test that Allocate() keeps its promise not to return a nullptr, even if
+// the BumpPtrAllocator performs a size-zero allocation when brand new.
+//
+// Optimizations disabled so we actually compare the pointer to nullptr,
+// instead of assuming the attribute is accurate.
+#pragma clang optimize off
+TEST(AllocatorTest, TestNeverNull) {
+  BumpPtrAllocator Alloc;
+
+  void *P = Alloc.Allocate(0, 1);
+
+  EXPECT_NE(P, nullptr);
+}
+#pragma clang optimize on
+
 }  // anonymous namespace
Index: include/llvm/Support/Allocator.h
===================================================================
--- include/llvm/Support/Allocator.h
+++ include/llvm/Support/Allocator.h
@@ -159,7 +159,7 @@
         CustomSizedSlabs(std::move(Old.CustomSizedSlabs)),
         BytesAllocated(Old.BytesAllocated), RedZoneSize(Old.RedZoneSize),
         Allocator(std::move(Old.Allocator)) {
-    Old.CurPtr = Old.End = nullptr;
+    Old.CurPtr = Old.End = const_cast<char *>(EmptySlabPtr);
     Old.BytesAllocated = 0;
     Old.Slabs.clear();
     Old.CustomSizedSlabs.clear();
@@ -182,7 +182,7 @@
     CustomSizedSlabs = std::move(RHS.CustomSizedSlabs);
     Allocator = std::move(RHS.Allocator);
 
-    RHS.CurPtr = RHS.End = nullptr;
+    RHS.CurPtr = RHS.End = const_cast<char *>(EmptySlabPtr);
     RHS.BytesAllocated = 0;
     RHS.Slabs.clear();
     RHS.CustomSizedSlabs.clear();
@@ -304,13 +304,17 @@
   }
 
 private:
+  /// Initial value for CurPtr and End. This should be a valid address
+  /// so we never return nullptr.
+  static const char EmptySlabPtr[];
+
   /// The current pointer into the current slab.
   ///
   /// This points to the next free byte in the slab.
-  char *CurPtr = nullptr;
+  char *CurPtr = const_cast<char *>(EmptySlabPtr);
 
   /// The end of the current slab.
-  char *End = nullptr;
+  char *End = const_cast<char *>(EmptySlabPtr);
 
   /// The slabs allocated so far.
   SmallVector<void *, 4> Slabs;
@@ -375,6 +379,9 @@
   template <typename T> friend class SpecificBumpPtrAllocator;
 };
 
+template <typename AllocatorT, size_t SlabSize, size_t SizeThreshold>
+const char BumpPtrAllocatorImpl<AllocatorT, SlabSize, SizeThreshold>::EmptySlabPtr[1] = {0};
+
 /// The standard BumpPtrAllocator which just uses the default template
 /// parameters.
 typedef BumpPtrAllocatorImpl<> BumpPtrAllocator;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D51317.162723.patch
Type: text/x-patch
Size: 2603 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180827/c22b7da9/attachment.bin>


More information about the llvm-commits mailing list