From 8fcf46ad75cb6b90adb3e3bb211fceaccca6e204 Mon Sep 17 00:00:00 2001
From: Nick Terrell <terrelln@fb.com>
Date: Wed, 25 Mar 2020 17:21:33 -0700
Subject: [PATCH] Mark destroyItem() as noexcept

Summary:
F14Node{Map,Set} doesn't require `is_nothrow_destructible<value_type>`.  `clear()` and the destructor are both marked `noexcept`, so they will both terminate if the destructor throws. But `erase()` is not marked `noexcept`, so when the destructor throws during `erase()` the value is left in the map. This could be problematic if the value is half destroyed, or if `eraseInto()` is used.

This diff fixes the problem by marking `destroyItem()` as `noexcept`, so `std::terminate` is called whenever the value destructor throws.

Reviewed By: nbronson

Differential Revision: D20604276

fbshipit-source-id: c52c932d78d6ed61368985a749adf77c27a5a0de
---
 folly/container/detail/F14Policy.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/folly/container/detail/F14Policy.h b/folly/container/detail/F14Policy.h
index 3763609e5..9c6b3bb8a 100644
--- a/folly/container/detail/F14Policy.h
+++ b/folly/container/detail/F14Policy.h
@@ -640,7 +640,7 @@ class ValueContainerPolicy : public BasePolicy<
     }
   }
 
-  void destroyItem(Item& item) {
+  void destroyItem(Item& item) noexcept {
     Alloc& a = this->alloc();
     auto ptr = std::addressof(item);
     AllocTraits::destroy(a, ptr);
@@ -876,7 +876,7 @@ class NodeContainerPolicy
     prefetchAddr(std::addressof(*item));
   }
 
-  void destroyItem(Item& item) {
+  void destroyItem(Item& item) noexcept {
     if (item != nullptr) {
       Alloc& a = this->alloc();
       AllocTraits::destroy(a, std::addressof(*item));
@@ -1252,7 +1252,7 @@ class VectorContainerPolicy : public BasePolicy<
     prefetchAddr(std::addressof(values_[item]));
   }
 
-  void destroyItem(Item&) {}
+  void destroyItem(Item&) noexcept {}
 
   template <typename T>
   std::enable_if_t<std::is_nothrow_move_constructible<T>::value>
-- 
2.26.2