Fix UBSAN failure in RangeTest.cpp with libstdc++-v4.9
[folly.git] / folly / PackedSyncPtr.h
index f7b753b8f062b30304d8286c510d851a53417819..a49b0270d0c25a23b699ab9b7701ee3cbfb927a7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * limitations under the License.
  */
 
-#ifndef FOLLY_PACKEDSYNCPTR_H_
-#define FOLLY_PACKEDSYNCPTR_H_
+#pragma once
+
+#include <type_traits>
+
+#include <glog/logging.h>
 
 #include <folly/Portability.h>
+#include <folly/SmallLocks.h>
 
-#if !FOLLY_X64
-# error "PackedSyncPtr is x64-specific code."
+#if !FOLLY_X64 && !FOLLY_PPC64 && !FOLLY_AARCH64
+#error "PackedSyncPtr is x64, ppc64 or aarch64 specific code."
 #endif
 
 /*
  * @author Jordan DeLong <delong.j@fb.com>
  */
 
-#include <folly/SmallLocks.h>
-#include <type_traits>
-#include <glog/logging.h>
-
 namespace folly {
 
-template<class T>
+template <class T>
 class PackedSyncPtr {
   // This just allows using this class even with T=void.  Attempting
   // to use the operator* or operator[] on a PackedSyncPtr<void> will
   // still properly result in a compile error.
   typedef typename std::add_lvalue_reference<T>::type reference;
 
-public:
+ public:
   /*
    * If you default construct one of these, you must call this init()
    * function before using it.
@@ -74,7 +74,7 @@ public:
    * (We are avoiding a constructor to ensure gcc allows us to put
    * this class in packed structures.)
    */
-  void init(T* initialPtr = 0, uint16_t initialExtra = 0) {
+  void init(T* initialPtr = nullptr, uint16_t initialExtra = 0) {
     auto intPtr = reinterpret_cast<uintptr_t>(initialPtr);
     CHECK(!(intPtr >> 48));
     data_.init(intPtr);
@@ -134,18 +134,20 @@ public:
     data_.setData((uintptr_t(extra) << 48) | ptr);
   }
 
-  // Logically private, but we can't have private data members and
-  // still be considered a POD.  (In C++11 we are still a standard
-  // layout struct if this is private, but it doesn't matter, since
-  // gcc (4.6) won't let us use this with attribute packed still in
-  // that case.)
+ private:
   PicoSpinLock<uintptr_t> data_;
-};
+} FOLLY_PACK_ATTR;
 
+static_assert(
+    std::is_pod<PackedSyncPtr<void>>::value,
+    "PackedSyncPtr must be kept a POD type.");
 static_assert(sizeof(PackedSyncPtr<void>) == 8,
               "PackedSyncPtr should be only 8 bytes---something is "
               "messed up");
 
+template <typename T>
+std::ostream& operator<<(std::ostream& os, const PackedSyncPtr<T>& ptr) {
+  os << "PackedSyncPtr(" << ptr.get() << ", " << ptr.extra() << ")";
+  return os;
 }
-
-#endif
+} // namespace folly