From acc25427270be8bb5b3cb7f3a86b90df29a35220 Mon Sep 17 00:00:00 2001 From: David Wells Date: Tue, 14 Jun 2022 16:23:48 -0400 Subject: [PATCH] Fix the MPI window functions with clang. libc++ defines std::unique_ptr::reset() as _LIBCPP_INLINE_VISIBILITY void reset(nullptr_t = nullptr) _NOEXCEPT { pointer __tmp = __ptr_.first(); __ptr_.first() = nullptr; if (__tmp) __ptr_.second()(__tmp); } The result of this is that aligned_vector->elements.get() is nullptr at the point at which we call the deleter - hence this deleter won't work correctly. We can work around this by avoiding std::unique_ptr::get() and just using our own member variables or ptr, which are guaranteed to be valid since they will not be set to nullptr by std::unique_ptr::reset(). --- include/deal.II/base/aligned_vector.h | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/include/deal.II/base/aligned_vector.h b/include/deal.II/base/aligned_vector.h index 7913f06a31..e27b872b3e 100644 --- a/include/deal.II/base/aligned_vector.h +++ b/include/deal.II/base/aligned_vector.h @@ -1128,13 +1128,18 @@ AlignedVector::Deleter::MPISharedMemDeleterAction::delete_array( T * ptr) { (void)ptr; - Assert(aligned_vector->elements.get() == ptr, ExcInternalError()); + // It would be nice to assert that aligned_vector->elements.get() equals ptr, + // but it is not guaranteed to work: clang, for example, sets elements.get() + // to nullptr and then calls the deleter on a previously made copy. Hence we + // must assume here that elements.get() (which is managed by the unique_ptr) + // may be nullptr at this point. + // + // used_elements_end is a member variable of AlignedVector (i.e., we control + // it, not unique_ptr) so it is still set to its correct value. if (is_shmem_root) if (std::is_trivial::value == false) - for (T *p = aligned_vector->used_elements_end - 1; - p >= aligned_vector->elements.get(); - --p) + for (T *p = aligned_vector->used_elements_end - 1; p >= ptr; --p) p->~T(); int ierr; -- 2.39.5