Add HB_FUNCOBJ()

Fixes https://github.com/harfbuzz/harfbuzz/issues/1651
diff --git a/src/hb-algs.hh b/src/hb-algs.hh
index c52ffec..5ee0a4c 100644
--- a/src/hb-algs.hh
+++ b/src/hb-algs.hh
@@ -1,5 +1,6 @@
 /*
  * Copyright © 2017  Google, Inc.
+ * Copyright © 2019  Google, Inc.
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
@@ -22,6 +23,7 @@
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Google Author(s): Behdad Esfahbod
+ * Facebook Author(s): Behdad Esfahbod
  */
 
 #ifndef HB_ALGS_HH
@@ -54,19 +56,19 @@
     /* Knuth's multiplicative method: */
     return (uint32_t) v * 2654435761u;
   }
-} static const hb_hash HB_UNUSED;
+} HB_FUNCOBJ (hb_hash);
 
-static const struct
+struct
 {
   template <typename T> T
   operator () (const T& v) const { return v; }
-} hb_identity HB_UNUSED;
+} HB_FUNCOBJ (hb_identity);
 
-static const struct
+struct
 {
   template <typename T> bool
   operator () (const T& v) const { return bool (v); }
-} hb_bool HB_UNUSED;
+} HB_FUNCOBJ (hb_bool);
 
 template <typename T1, typename T2>
 struct hb_pair_t
@@ -86,28 +88,28 @@
 template <typename T1, typename T2> static inline hb_pair_t<T1, T2>
 hb_pair (T1&& a, T2&& b) { return hb_pair_t<T1, T2> (a, b); }
 
-static const struct
+struct
 {
   template <typename Pair> decltype (hb_declval (Pair).first)
   operator () (const Pair& pair) const { return pair.first; }
-} hb_first HB_UNUSED;
+} HB_FUNCOBJ (hb_first);
 
-static const struct
+struct
 {
   template <typename Pair> decltype (hb_declval (Pair).second)
   operator () (const Pair& pair) const { return pair.second; }
-} hb_second HB_UNUSED;
+} HB_FUNCOBJ (hb_second);
 
-static const struct
+struct
 {
   template <typename T, typename T2> T
   operator () (const T& a, const T2& b) const { return a <= b ? a : b; }
-} hb_min HB_UNUSED;
-static const struct
+} HB_FUNCOBJ (hb_min);
+struct
 {
   template <typename T, typename T2> T
   operator () (const T& a, const T2& b) const { return a >= b ? a : b; }
-} hb_max HB_UNUSED;
+} HB_FUNCOBJ (hb_max);
 
 
 /*
diff --git a/src/hb-iter.hh b/src/hb-iter.hh
index 6f8e7ec..a75be85 100644
--- a/src/hb-iter.hh
+++ b/src/hb-iter.hh
@@ -1,5 +1,6 @@
 /*
  * Copyright © 2018  Google, Inc.
+ * Copyright © 2019  Google, Inc.
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
@@ -22,6 +23,7 @@
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Google Author(s): Behdad Esfahbod
+ * Facebook Author(s): Behdad Esfahbod
  */
 
 #ifndef HB_ITER_HH
@@ -130,7 +132,7 @@
 
 template <typename> struct hb_array_t;
 
-static const struct
+struct
 {
   template <typename T>
   hb_iter_t (T)
@@ -147,7 +149,7 @@
   operator () (Type (&array)[length]) const
   { return hb_array_t<Type> (array, length); }
 
-} hb_iter HB_UNUSED;
+} HB_FUNCOBJ (hb_iter);
 
 
 /* Mixin to fill in what the subclass doesn't provide. */
@@ -298,13 +300,13 @@
   private:
   Proj f;
 };
-static const struct
+struct
 {
   template <typename Proj>
   hb_map_iter_factory_t<Proj>
   operator () (Proj&& f) const
   { return hb_map_iter_factory_t<Proj> (f); }
-} hb_map HB_UNUSED;
+} HB_FUNCOBJ (hb_map);
 
 template <typename Iter, typename Pred, typename Proj,
 	 hb_enable_if (hb_is_iterator (Iter))>
@@ -342,14 +344,14 @@
   Pred p;
   Proj f;
 };
-static const struct
+struct
 {
   template <typename Pred = decltype ((hb_bool)),
 	    typename Proj = decltype ((hb_identity))>
   hb_filter_iter_factory_t<Pred, Proj>
   operator () (Pred&& p = hb_bool, Proj&& f = hb_identity) const
   { return hb_filter_iter_factory_t<Pred, Proj> (p, f); }
-} hb_filter HB_UNUSED;
+} HB_FUNCOBJ (hb_filter);
 
 template <typename Redu, typename InitT>
 struct hb_reduce_t
@@ -372,13 +374,13 @@
   Redu r;
   InitT init_value;
 };
-static const struct
+struct
 {
   template <typename Redu, typename InitT>
   hb_reduce_t<Redu, InitT>
   operator () (Redu&& r, InitT init_value) const
   { return hb_reduce_t<Redu, InitT> (r, init_value); }
-} hb_reduce HB_UNUSED;
+} HB_FUNCOBJ (hb_reduce);
 
 
 /* hb_zip() */
@@ -411,14 +413,14 @@
   A a;
   B b;
 };
-static const struct
+struct
 {
   template <typename A, typename B,
 	    hb_enable_if (hb_is_iterable (A) && hb_is_iterable (B))>
   hb_zip_iter_t<hb_iter_t (A), hb_iter_t (B)>
   operator () (A& a, B &b) const
   { return hb_zip_iter_t<hb_iter_t (A), hb_iter_t (B)> (hb_iter (a), hb_iter (b)); }
-} hb_zip HB_UNUSED;
+} HB_FUNCOBJ (hb_zip);
 
 /* hb_enumerate */
 
@@ -446,14 +448,14 @@
   unsigned i;
   Iter it;
 };
-static const struct
+struct
 {
   template <typename Iterable,
 	    hb_enable_if (hb_is_iterable (Iterable))>
   hb_enumerate_iter_t<hb_iter_t (Iterable)>
   operator () (Iterable& it) const
   { return hb_enumerate_iter_t<hb_iter_t (Iterable)> (hb_iter (it)); }
-} hb_enumerate HB_UNUSED;
+} HB_FUNCOBJ (hb_enumerate);
 
 /* hb_apply() */
 
@@ -474,7 +476,7 @@
   private:
   Appl a;
 };
-static const struct
+struct
 {
   template <typename Appl> hb_apply_t<Appl>
   operator () (Appl&& a) const
@@ -483,7 +485,7 @@
   template <typename Appl> hb_apply_t<Appl&>
   operator () (Appl *a) const
   { return hb_apply_t<Appl&> (*a); }
-} hb_apply HB_UNUSED;
+} HB_FUNCOBJ (hb_apply);
 
 /* hb_sink() */
 
@@ -504,7 +506,7 @@
   private:
   Sink s;
 };
-static const struct
+struct
 {
   template <typename Sink> hb_sink_t<Sink>
   operator () (Sink&& s) const
@@ -513,11 +515,11 @@
   template <typename Sink> hb_sink_t<Sink&>
   operator () (Sink *s) const
   { return hb_sink_t<Sink&> (*s); }
-} hb_sink HB_UNUSED;
+} HB_FUNCOBJ (hb_sink);
 
 /* hb-drain: hb_sink to void / blackhole / /dev/null. */
 
-static const struct
+struct
 {
   template <typename Iter,
 	    hb_enable_if (hb_is_iterator (Iter))>
@@ -527,7 +529,7 @@
     for (; it; ++it)
       (void) *it;
   }
-} hb_drain HB_UNUSED;
+} HB_FUNCOBJ (hb_drain);
 
 /* hb_unzip(): unzip and sink to two sinks. */
 
@@ -553,7 +555,7 @@
   Sink1 s1;
   Sink2 s2;
 };
-static const struct
+struct
 {
   template <typename Sink1, typename Sink2> hb_unzip_t<Sink1, Sink2>
   operator () (Sink1&& s1, Sink2&& s2) const
@@ -562,12 +564,12 @@
   template <typename Sink1, typename Sink2> hb_unzip_t<Sink1&, Sink2&>
   operator () (Sink1 *s1, Sink2 *s2) const
   { return hb_unzip_t<Sink1&, Sink2&> (*s1, *s2); }
-} hb_unzip HB_UNUSED;
+} HB_FUNCOBJ (hb_unzip);
 
 
 /* hb-all, hb-any, hb-none. */
 
-static const struct
+struct
 {
   template <typename Iterable,
 	    hb_enable_if (hb_is_iterable (Iterable))>
@@ -579,9 +581,8 @@
 	return false;
     return true;
   }
-} hb_all HB_UNUSED;
-
-static const struct
+} HB_FUNCOBJ (hb_all);
+struct
 {
   template <typename Iterable,
 	    hb_enable_if (hb_is_iterable (Iterable))>
@@ -593,9 +594,8 @@
 	return true;
     return false;
   }
-} hb_any HB_UNUSED;
-
-static const struct
+} HB_FUNCOBJ (hb_any);
+struct
 {
   template <typename Iterable,
 	    hb_enable_if (hb_is_iterable (Iterable))>
@@ -607,7 +607,7 @@
 	return false;
     return true;
   }
-} hb_none HB_UNUSED;
+} HB_FUNCOBJ (hb_none);
 
 /*
  * Algorithms operating on iterators.
diff --git a/src/hb-meta.hh b/src/hb-meta.hh
index c7c91ea..a711219 100644
--- a/src/hb-meta.hh
+++ b/src/hb-meta.hh
@@ -34,18 +34,22 @@
  * C++ template meta-programming & fundamentals used with them.
  */
 
+#define HB_FUNCOBJ(x) static_const x HB_UNUSED
 
-template <typename T> static inline T*
-hb_addressof (const T& arg)
+struct
 {
+  template <typename T>
+  T* operator () (const T& arg) const
+  {
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wcast-align"
-  /* https://en.cppreference.com/w/cpp/memory/addressof */
-  return reinterpret_cast<T*>(
-	   &const_cast<char&>(
-	      reinterpret_cast<const volatile char&>(arg)));
+    /* https://en.cppreference.com/w/cpp/memory/addressof */
+    return reinterpret_cast<T*> (
+	     &const_cast<char&> (
+		reinterpret_cast<const volatile char&> (arg)));
 #pragma GCC diagnostic pop
-}
+  }
+} HB_FUNCOBJ (hb_addressof);
 
 template <typename T> static inline T hb_declval ();
 #define hb_declval(T) (hb_declval<T> ())
@@ -63,13 +67,13 @@
 #define hb_remove_pointer(T) typename hb_match_pointer<T>::type
 #define hb_is_pointer(T) hb_match_pointer<T>::value
 
-static const struct
+struct
 {
   template <typename T>
   T operator () (T v) const { return v; }
   template <typename T>
   T& operator () (T *v) const { return *v; }
-} hb_deref_pointer HB_UNUSED;
+} HB_FUNCOBJ (hb_deref_pointer);
 
 
 /* std::move and std::forward */
diff --git a/src/hb.hh b/src/hb.hh
index 4ea1097..172b6ac 100644
--- a/src/hb.hh
+++ b/src/hb.hh
@@ -260,6 +260,13 @@
 # endif
 #endif
 
+/* https://github.com/harfbuzz/harfbuzz/issues/1651 */
+#if defined(__clang__) && __clang_major__ < 10
+#define static_const static
+#else
+#define static_const static const
+#endif
+
 #if defined(__GNUC__) && (__GNUC__ >= 3)
 #define HB_FUNC __PRETTY_FUNCTION__
 #elif defined(_MSC_VER)