Fix optional default initialization
authorMatthieu Martin <matthieu@fb.com>
Wed, 5 Oct 2016 06:28:35 +0000 (23:28 -0700)
committerFacebook Github Bot <facebook-github-bot-bot@fb.com>
Wed, 5 Oct 2016 06:38:30 +0000 (23:38 -0700)
Summary: Initialize Optional internal memory, so that "un-initialized memory" tools don't flag its callsites.

Reviewed By: yfeldblum

Differential Revision: D3960462

fbshipit-source-id: 3bd0109959fb93e040fa2e874f586b3508e46dd2

folly/Optional.h

index e897c38bfb0ed91836be732cabe5d0716162107d..f00a40e14a0950bcd3f86096c23a234204e5f5c2 100644 (file)
@@ -67,17 +67,6 @@ typedef int detail::NoneHelper::*None;
 
 const None none = nullptr;
 
-/**
- * gcc-4.7 warns about use of uninitialized memory around the use of storage_
- * even though this is explicitly initialized at each point.
- */
-#if defined(__GNUC__) && !defined(__clang__)
-# pragma GCC diagnostic push
-# pragma GCC diagnostic ignored "-Wuninitialized"
-# pragma GCC diagnostic ignored "-Wpragmas"
-# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
-#endif // __GNUC__
-
 class OptionalEmptyException : public std::runtime_error {
  public:
   OptionalEmptyException()
@@ -273,9 +262,18 @@ class Optional {
   }
 
   struct StorageTriviallyDestructible {
-    // uninitialized
-    union { Value value; };
-    bool hasValue;
+    // The union trick allows to initialize the Optional's memory,
+    // so that compiler/tools don't complain about unitialized memory,
+    // without actually calling Value's default constructor.
+    // The rest of the implementation enforces that hasValue/value are
+    // synchronized.
+    union {
+      bool hasValue;
+      struct {
+        bool paddingForHasValue_[1];
+        Value value;
+      };
+    };
 
     StorageTriviallyDestructible() : hasValue{false} {}
 
@@ -285,12 +283,16 @@ class Optional {
   };
 
   struct StorageNonTriviallyDestructible {
-    // uninitialized
-    union { Value value; };
-    bool hasValue;
+    // See StorageTriviallyDestructible's union
+    union {
+      bool hasValue;
+      struct {
+        bool paddingForHasValue_[1];
+        Value value;
+      };
+    };
 
     StorageNonTriviallyDestructible() : hasValue{false} {}
-
     ~StorageNonTriviallyDestructible() {
       clear();
     }
@@ -311,10 +313,6 @@ class Optional {
   Storage storage_;
 };
 
-#if defined(__GNUC__) && !defined(__clang__)
-#pragma GCC diagnostic pop
-#endif
-
 template<class T>
 const T* get_pointer(const Optional<T>& opt) {
   return opt.get_pointer();