Add a "shim" to allow use of Clang 5's __builtin_available everywhere

This is mostly relevant for Apple platforms, where we can use the new
unguarded availability warnings to guarantee that proper version checks
are present when using APIs that are not necessarily available on the
deployment target.

Change-Id: Ie408704b2924e1220491a9ea30f0141dfa4867d9
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Jake Petroules 2017-09-22 00:35:24 -07:00
parent 9d2cdb163f
commit 70422449ef
2 changed files with 74 additions and 0 deletions

View File

@ -1,5 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Copyright (C) 2015 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@ -59,5 +60,77 @@
#include <QtCore/private/qtcore-config_p.h>
#endif
#if defined(__cplusplus)
#if !QT_HAS_BUILTIN(__builtin_available)
#include <initializer_list>
#include <QtCore/qoperatingsystemversion.h>
#include <QtCore/qversionnumber.h>
QT_BEGIN_NAMESPACE
struct qt_clang_builtin_available_os_version_data {
QOperatingSystemVersion::OSType type;
const char *version;
};
static inline bool qt_clang_builtin_available(
const std::initializer_list<qt_clang_builtin_available_os_version_data> &versions)
{
for (auto it = versions.begin(); it != versions.end(); ++it) {
if (QOperatingSystemVersion::currentType() == it->type) {
const auto current = QOperatingSystemVersion::current();
return QVersionNumber(
current.majorVersion(),
current.minorVersion(),
current.microVersion()) >= QVersionNumber::fromString(
QString::fromLatin1(it->version));
}
}
// Result is true if the platform is not any of the checked ones; this matches behavior of
// LLVM __builtin_available and @available constructs
return true;
}
QT_END_NAMESPACE
#define QT_AVAILABLE_OS_VER(os, ver) \
QT_PREPEND_NAMESPACE(qt_clang_builtin_available_os_version_data){\
QT_PREPEND_NAMESPACE(QOperatingSystemVersion)::os, #ver}
#define QT_AVAILABLE_CAT(L, R) QT_AVAILABLE_CAT_(L, R)
#define QT_AVAILABLE_CAT_(L, R) L ## R
#define QT_AVAILABLE_EXPAND(...) QT_AVAILABLE_OS_VER(__VA_ARGS__)
#define QT_AVAILABLE_SPLIT(os_ver) QT_AVAILABLE_EXPAND(QT_AVAILABLE_CAT(QT_AVAILABLE_SPLIT_, os_ver))
#define QT_AVAILABLE_SPLIT_macOS MacOS,
#define QT_AVAILABLE_SPLIT_iOS IOS,
#define QT_AVAILABLE_SPLIT_tvOS TvOS,
#define QT_AVAILABLE_SPLIT_watchOS WatchOS,
#define QT_BUILTIN_AVAILABLE0(e) \
QT_PREPEND_NAMESPACE(qt_clang_builtin_available)({})
#define QT_BUILTIN_AVAILABLE1(a, e) \
QT_PREPEND_NAMESPACE(qt_clang_builtin_available)({QT_AVAILABLE_SPLIT(a)})
#define QT_BUILTIN_AVAILABLE2(a, b, e) \
QT_PREPEND_NAMESPACE(qt_clang_builtin_available)({QT_AVAILABLE_SPLIT(a), \
QT_AVAILABLE_SPLIT(b)})
#define QT_BUILTIN_AVAILABLE3(a, b, c, e) \
QT_PREPEND_NAMESPACE(qt_clang_builtin_available)({QT_AVAILABLE_SPLIT(a), \
QT_AVAILABLE_SPLIT(b), \
QT_AVAILABLE_SPLIT(c)})
#define QT_BUILTIN_AVAILABLE4(a, b, c, d, e) \
QT_PREPEND_NAMESPACE(qt_clang_builtin_available)({QT_AVAILABLE_SPLIT(a), \
QT_AVAILABLE_SPLIT(b), \
QT_AVAILABLE_SPLIT(c), \
QT_AVAILABLE_SPLIT(d)})
#define QT_BUILTIN_AVAILABLE_ARG(arg0, arg1, arg2, arg3, arg4, arg5, ...) arg5
#define QT_BUILTIN_AVAILABLE_CHOOSER(...) QT_BUILTIN_AVAILABLE_ARG(__VA_ARGS__, \
QT_BUILTIN_AVAILABLE4, \
QT_BUILTIN_AVAILABLE3, \
QT_BUILTIN_AVAILABLE2, \
QT_BUILTIN_AVAILABLE1, \
QT_BUILTIN_AVAILABLE0, )
#define __builtin_available(...) QT_BUILTIN_AVAILABLE_CHOOSER(__VA_ARGS__)(__VA_ARGS__)
#endif // !QT_HAS_BUILTIN(__builtin_available)
#endif // defined(__cplusplus)
#endif // QGLOBAL_P_H

View File

@ -81,6 +81,7 @@ SOURCES += \
../../corelib/tools/qstringbuilder.cpp \
../../corelib/tools/qstring_compat.cpp \
../../corelib/tools/qstringlist.cpp \
../../corelib/tools/qversionnumber.cpp \
../../corelib/tools/qvsnprintf.cpp \
../../corelib/xml/qxmlutils.cpp \
../../corelib/xml/qxmlstream.cpp \