Bug 906783 - Attempt to detect the standard C++ library version, r=Waldo

This commit is contained in:
Joshua Cranmer 2013-08-29 22:44:23 -05:00
parent df9126512e
commit 642e66f518
2 changed files with 81 additions and 25 deletions

View File

@ -18,6 +18,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/Compiler.h"
#include "mozilla/TypeTraits.h"
#include <stdint.h>
@ -27,34 +28,16 @@
* 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

View File

@ -29,4 +29,77 @@
#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 */