Bug 906783 - Attempt to detect the standard C++ library version, r=Waldo
authorJoshua Cranmer <Pidgeot18@gmail.com>
Thu, 29 Aug 2013 22:44:23 -0500
changeset 145081 195e0c04ae2802f47d8e5f82b3d98d57f90bd254
parent 145080 ee3a0dcb266bd2378dab8eb9ff134c0dbf160a79
child 145082 2d20975bbdb9049a8516e6ef567831562aa9e83b
push id25192
push useremorley@mozilla.com
push dateFri, 30 Aug 2013 16:23:44 +0000
treeherdermozilla-central@cfe8b0ab6d59 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs906783
milestone26.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 906783 - Attempt to detect the standard C++ library version, r=Waldo
mfbt/Atomics.h
mfbt/Compiler.h
--- a/mfbt/Atomics.h
+++ b/mfbt/Atomics.h
@@ -13,53 +13,36 @@
  * sent a copy of this header and the C++11 standard.
  */
 
 #ifndef mozilla_Atomics_h
 #define mozilla_Atomics_h
 
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/Compiler.h"
 #include "mozilla/TypeTraits.h"
 
 #include <stdint.h>
 
 /*
  * Our minimum deployment target on clang/OS X is OS X 10.6, whose SDK
  * does not have <atomic>.  So be sure to check for <atomic> support
  * along with C++0x support.
  */
-#if defined(__clang__)
+#if defined(__clang__) || defined(__GNUC__)
    /*
-    * clang doesn't like libstdc++'s version of <atomic> before GCC 4.7,
-    * due to the loose typing of the __sync_* family of functions done by
-    * GCC.  We do not have a particularly good way to detect this sort of
-    * case at this point, so just assume that if we're on a Linux system,
-    * we can't use the system's <atomic>.
-    *
-    * OpenBSD uses an old libstdc++ 4.2.1 and thus doesnt have <atomic>.
+    * Clang doesn't like <atomic> from libstdc++ before 4.7 due to the
+    * loose typing of the atomic builtins. GCC 4.5 and 4.6 lacks inline
+    * definitions for unspecialized std::atomic and causes linking errors.
+    * Therefore, we require at least 4.7.0 for using libstdc++.
     */
-#  if !defined(__linux__) && !defined(__OpenBSD__) && \
-      (__cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)) && \
-      __has_include(<atomic>)
+#  if MOZ_USING_LIBSTDCXX && MOZ_LIBSTDCXX_VERSION_AT_LEAST(4, 7, 0)
 #    define MOZ_HAVE_CXX11_ATOMICS
-#  endif
-/*
- * Android uses a different C++ standard library that does not provide
- * support for <atomic>.
- *
- * GCC 4.5.x and 4.6.x's unspecialized std::atomic template doesn't include
- * inline definitions for the functions declared therein.  This oversight
- * leads to linking errors when using atomic enums.  We therefore require
- * GCC 4.7 or higher.
- */
-#elif defined(__GNUC__) && !defined(__ANDROID__)
-#  include "mozilla/Compiler.h"
-#  if (defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L) && \
-      MOZ_GCC_VERSION_AT_LEAST(4, 7, 0)
+#  elif MOZ_USING_LIBCXX
 #    define MOZ_HAVE_CXX11_ATOMICS
 #  endif
 #elif defined(_MSC_VER) && _MSC_VER >= 1700
 #  define MOZ_HAVE_CXX11_ATOMICS
 #endif
 
 namespace mozilla {
 
--- a/mfbt/Compiler.h
+++ b/mfbt/Compiler.h
@@ -24,9 +24,82 @@
 #endif
 
 #else
 
 #define MOZ_IS_GCC 0
 
 #endif
 
+/*
+ * The situation with standard libraries is a lot worse than with compilers,
+ * particularly as clang and gcc could end up using one of three or so standard
+ * libraries, and they may not be up-to-snuff with newer C++11 versions. To
+ * detect the library, we're going to include cstddef (which is a small header
+ * which will be transitively included by everybody else at some point) to grab
+ * the version macros and deduce macros from there.
+ */
+#ifdef __cplusplus
+#  include <cstddef>
+#  ifdef _STLPORT_MAJOR
+#    define MOZ_USING_STLPORT 1
+#    define MOZ_STLPORT_VERSION_AT_LEAST(major, minor, patch) \
+       (_STLPORT_VERSION >= ((major) << 8 | (minor) << 4 | (patch)))
+#  elif defined(__LIBCPP_VERSION)
+   /*
+    * libc++, unfortunately, doesn't appear to have useful versioning macros.
+    * Hopefully, the recommendations of N3694 with respect to standard libraries
+    * will get applied instead and we won't need to worry about version numbers
+    * here.
+    */
+#    define MOZ_USING_LIBCXX 1
+#  elif defined(__GLIBCXX__)
+#    define MOZ_USING_LIBSTDCXX 1
+   /*
+    * libstdc++ is also annoying and doesn't give us useful versioning macros
+    * for the library. If we're using gcc, then assume that libstdc++ matches
+    * the compiler version. If we're using clang, we're going to have to fake
+    * major/minor combinations by looking for newly-defined config macros.
+    */
+#    if MOZ_IS_GCC
+#      define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \
+          MOZ_GCC_VERSION_AT_LEAST(major, minor, patch)
+#    elif defined(_GLIBCXX_THROW_OR_ABORT)
+#      define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \
+          ((major) < 4 || ((major) == 4 && (minor) <= 8))
+#    elif defined(_GLIBCXX_NOEXCEPT)
+#      define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \
+          ((major) < 4 || ((major) == 4 && (minor) <= 7))
+#    elif defined(_GLIBCXX_USE_DEPRECATED)
+#      define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \
+          ((major) < 4 || ((major) == 4 && (minor) <= 6))
+#    elif defined(_GLIBCXX_PSEUDO_VISIBILITY)
+#      define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \
+          ((major) < 4 || ((major) == 4 && (minor) <= 5))
+#    elif defined(_GLIBCXX_BEGIN_EXTERN_C)
+#      define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \
+          ((major) < 4 || ((major) == 4 && (minor) <= 4))
+#    elif defined(_GLIBCXX_VISIBILITY_ATTR)
+#      define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \
+          ((major) < 4 || ((major) == 4 && (minor) <= 3))
+#    elif defined(_GLIBCXX_VISIBILITY)
+#      define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \
+          ((major) < 4 || ((major) == 4 && (minor) <= 2))
+#    else
+#      error "Your version of libstdc++ is unknown to us and is likely too old."
+#    endif
+#  endif
+
+   // Flesh out the defines for everyone else
+#  ifndef MOZ_USING_STLPORT
+#    define MOZ_USING_STLPORT 0
+#    define MOZ_STLPORT_VERSION_AT_LEAST(major, minor, patch) 0
+#  endif
+#  ifndef MOZ_USING_LIBCXX
+#    define MOZ_USING_LIBCXX 0
+#  endif
+#  ifndef MOZ_USING_LIBSTDCXX
+#    define MOZ_USING_LIBSTDCXX 0
+#    define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) 0
+#  endif
+#endif /* __cplusplus */
+
 #endif /* mozilla_Compiler_h */