Index: include/llvm/Support/Allocator.h =================================================================== --- include/llvm/Support/Allocator.h +++ include/llvm/Support/Allocator.h @@ -213,6 +213,7 @@ LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void * Allocate(size_t Size, size_t Alignment) { assert(Alignment > 0 && "0-byte alignnment is not allowed. Use 1 instead."); + Size = std::max(size_t(1), Size); // Keep track of how many bytes we've allocated. BytesAllocated += Size; Index: unittests/Support/AllocatorTest.cpp =================================================================== --- unittests/Support/AllocatorTest.cpp +++ unittests/Support/AllocatorTest.cpp @@ -185,4 +185,29 @@ EXPECT_GT(MockSlabAllocator::GetLastSlabSize(), 4096u); } +// Test that Allocate() behaves properly when asked to allocate zero bytes. +// +// Optimizations disabled so the compiler does not assume the pointer cannot +// be null because of Allocate()'s LLVM_ATTRIBUTE_RETURNS_NONNULL attribute. +#pragma clang optimize off +TEST(AllocatorTest, EmptyAllocation) { + BumpPtrAllocator Alloc; + + // Doesn't return null for an initial zero-size allocation. + void *a = Alloc.Allocate(0, 1); + EXPECT_NE(a, nullptr); + + // Doesn't return the same pointer for two different allocations. + void *b = Alloc.Allocate(0, 1); + EXPECT_NE(b, a); + + // Doesn't waste more space than necessary to get unique addresses. + EXPECT_EQ((char*)b - (char*)a, 1); + + // Zero-size allocation pointers are aligned. + void * c = Alloc.Allocate(0, 8); + EXPECT_EQ(alignmentAdjustment(c, 8), 0); +} +#pragma clang optimize on + } // anonymous namespace