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(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(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(EmptySlabPtr); /// The end of the current slab. - char *End = nullptr; + char *End = const_cast(EmptySlabPtr); /// The slabs allocated so far. SmallVector Slabs; @@ -375,6 +379,9 @@ template friend class SpecificBumpPtrAllocator; }; +template +const char BumpPtrAllocatorImpl::EmptySlabPtr[1] = {0}; + /// The standard BumpPtrAllocator which just uses the default template /// parameters. typedef BumpPtrAllocatorImpl<> BumpPtrAllocator; 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