diff --git a/llvm/include/llvm/ADT/SmallVector.h b/llvm/include/llvm/ADT/SmallVector.h --- a/llvm/include/llvm/ADT/SmallVector.h +++ b/llvm/include/llvm/ADT/SmallVector.h @@ -60,7 +60,7 @@ /// This is an implementation of the grow() method which only works /// on POD-like data types and is out of line to reduce code duplication. /// This function will report a fatal error if it cannot increase capacity. - void grow_pod(void *FirstEl, size_t MinCapacity, size_t TSize); + void grow_pod(void *FirstEl, size_t MinSize, size_t TSize); public: size_t size() const { return Size; } @@ -115,8 +115,8 @@ protected: SmallVectorTemplateCommon(size_t Size) : Base(getFirstEl(), Size) {} - void grow_pod(size_t MinCapacity, size_t TSize) { - Base::grow_pod(getFirstEl(), MinCapacity, TSize); + void grow_pod(size_t MinSize, size_t TSize) { + Base::grow_pod(getFirstEl(), MinSize, TSize); } /// Return true if this is a smallvector which has not had dynamic @@ -268,16 +268,32 @@ void SmallVectorTemplateBase::grow(size_t MinSize) { // Ensure we can fit the new capacity. // This is only going to be applicable when the capacity is 32 bit. - if (MinSize > this->SizeTypeMax()) - report_bad_alloc_error("SmallVector capacity overflow during allocation"); + if (MinSize > this->SizeTypeMax()) { + std::string Reason = "SmallVector unable to grow. Requested capacity (" + + std::to_string(MinSize) + + ") is larger than maximum value for size type (" + + std::to_string(this->SizeTypeMax()) + ")"; +#ifdef LLVM_ENABLE_EXCEPTIONS + throw std::length_error(Reason); +#else + report_fatal_error(Reason); +#endif + } // Ensure we can meet the guarantee of space for at least one more element. // The above check alone will not catch the case where grow is called with a - // default MinCapacity of 0, but the current capacity cannot be increased. + // default MinSize of 0, but the current capacity cannot be increased. // This is only going to be applicable when the capacity is 32 bit. - if (this->capacity() == this->SizeTypeMax()) - report_bad_alloc_error("SmallVector capacity unable to grow"); - + if (this->capacity() == this->SizeTypeMax()) { + std::string Reason = + "SmallVector capacity unable to grow. Already at maximum size " + + std::to_string(this->SizeTypeMax()); +#ifdef LLVM_ENABLE_EXCEPTIONS + throw std::length_error(Reason); +#else + report_fatal_error(Reason); +#endif + } // Always grow, even from zero. size_t NewCapacity = size_t(NextPowerOf2(this->capacity() + 2)); NewCapacity = std::min(std::max(NewCapacity, MinSize), this->SizeTypeMax()); diff --git a/llvm/include/llvm/Support/ErrorHandling.h b/llvm/include/llvm/Support/ErrorHandling.h --- a/llvm/include/llvm/Support/ErrorHandling.h +++ b/llvm/include/llvm/Support/ErrorHandling.h @@ -110,9 +110,9 @@ /// the following unwind succeeds, e.g. do not trigger additional allocations /// in the unwind chain. /// -/// If no error handler is installed (default), then a bad_alloc exception -/// is thrown, if LLVM is compiled with exception support, otherwise an -/// assertion is called. +/// If no error handler is installed (default), throws a bad_alloc exception +/// if LLVM is compiled with exception support. Otherwise prints the error +/// to standard error and calls abort(). LLVM_ATTRIBUTE_NORETURN void report_bad_alloc_error(const char *Reason, bool GenCrashDiag = true); diff --git a/llvm/lib/Support/ErrorHandling.cpp b/llvm/lib/Support/ErrorHandling.cpp --- a/llvm/lib/Support/ErrorHandling.cpp +++ b/llvm/lib/Support/ErrorHandling.cpp @@ -168,9 +168,11 @@ #else // Don't call the normal error handler. It may allocate memory. Directly write // an OOM to stderr and abort. - char OOMMessage[] = "LLVM ERROR: out of memory\n"; - ssize_t written = ::write(2, OOMMessage, strlen(OOMMessage)); - (void)written; + const char *OOMMessage = "LLVM ERROR: out of memory\n"; + const char *Newline = "\n"; + (void)::write(2, OOMMessage, strlen(OOMMessage)); + (void)::write(2, Reason, strlen(Reason)); + (void)::write(2, Newline, strlen(Newline)); abort(); #endif } diff --git a/llvm/lib/Support/SmallVector.cpp b/llvm/lib/Support/SmallVector.cpp --- a/llvm/lib/Support/SmallVector.cpp +++ b/llvm/lib/Support/SmallVector.cpp @@ -44,24 +44,40 @@ // Note: Moving this function into the header may cause performance regression. template -void SmallVectorBase::grow_pod(void *FirstEl, size_t MinCapacity, +void SmallVectorBase::grow_pod(void *FirstEl, size_t MinSize, size_t TSize) { // Ensure we can fit the new capacity. // This is only going to be applicable when the capacity is 32 bit. - if (MinCapacity > SizeTypeMax()) - report_bad_alloc_error("SmallVector capacity overflow during allocation"); + if (MinSize > SizeTypeMax()) { + std::string Reason = "SmallVector unable to grow. Requested capacity (" + + std::to_string(MinSize) + + ") is larger than maximum value for size type (" + + std::to_string(SizeTypeMax()) + ")"; +#ifdef LLVM_ENABLE_EXCEPTIONS + throw std::length_error(Reason); +#else + report_fatal_error(Reason); +#endif + } // Ensure we can meet the guarantee of space for at least one more element. // The above check alone will not catch the case where grow is called with a - // default MinCapacity of 0, but the current capacity cannot be increased. + // default MinSize of 0, but the current capacity cannot be increased. // This is only going to be applicable when the capacity is 32 bit. - if (capacity() == SizeTypeMax()) - report_bad_alloc_error("SmallVector capacity unable to grow"); + if (capacity() == SizeTypeMax()) { + std::string Reason = + "SmallVector capacity unable to grow. Already at maximum size " + + std::to_string(SizeTypeMax()); +#ifdef LLVM_ENABLE_EXCEPTIONS + throw std::length_error(Reason); +#endif + report_fatal_error(Reason); + } // In theory 2*capacity can overflow if the capacity is 64 bit, but the // original capacity would never be large enough for this to be a problem. size_t NewCapacity = 2 * capacity() + 1; // Always grow. - NewCapacity = std::min(std::max(NewCapacity, MinCapacity), SizeTypeMax()); + NewCapacity = std::min(std::max(NewCapacity, MinSize), SizeTypeMax()); void *NewElts; if (BeginX == FirstEl) {