96 lines
2.7 KiB
C++
96 lines
2.7 KiB
C++
/*
|
|
* MIT License
|
|
* Copyright (c) 2020 Rich Felker musl-libc
|
|
*/
|
|
|
|
#ifndef _FEATURES_H__RELIBC
|
|
#define _FEATURES_H__RELIBC
|
|
|
|
// Version metadata for feature gating
|
|
// This is useful for divergent implementation specific behavior
|
|
// glibc, ulibc, and likely others define a similar macro
|
|
// musl does not define an equivalent macro
|
|
#define __RELIBC__ 1
|
|
#define __RELIBC__MAJOR 0
|
|
#define __RELIBC__MINOR 2
|
|
|
|
/*
|
|
* Sources:
|
|
* https://en.cppreference.com/w/c/language/attributes
|
|
* https://clang.llvm.org/docs/LanguageExtensions.html
|
|
* https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005fc_005fattribute.html
|
|
* https://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html
|
|
*/
|
|
|
|
// Clang doesn't define __has_cpp_attribute if compiling C code
|
|
#if !defined(__has_cpp_attribute)
|
|
#define __has_cpp_attribute(x) 0
|
|
#endif
|
|
|
|
// Clang doesn't define __has_c_attribute if compiling C++ code
|
|
#if !defined(__has_c_attribute)
|
|
#define __has_c_attribute(x) 0
|
|
#endif
|
|
|
|
// Check if C23+ attributes are available
|
|
#if defined(__cplusplus)
|
|
// HACK: GCC backports C++ attributes to C++98 but doesn't accept attributes
|
|
// placed before the function like cbindgen emits.
|
|
// Let's just disable attributes for C++98 by checking if a random C++11
|
|
// feature is available.
|
|
#define __HAS_ATTRIBUTE(x) __cpp_variable_templates &&__has_cpp_attribute(x)
|
|
#else
|
|
#define __HAS_ATTRIBUTE(x) \
|
|
(__has_c_attribute(x) || __STDC_VERSION__ >= 202311L || \
|
|
__has_cpp_attribute(x))
|
|
#endif
|
|
|
|
// TODO: Not emitted with cbindgen
|
|
#if __STDC_VERSION__ >= 199901L
|
|
#define __restrict restrict
|
|
#elif !defined(__GNUC__)
|
|
#define __restrict
|
|
#endif
|
|
|
|
// TODO: Not emitted with cbindgen
|
|
#if __STDC_VERSION__ >= 199901L || defined(__cplusplus)
|
|
#define __inline inline
|
|
#elif !defined(__GNUC__)
|
|
#define __inline
|
|
#endif
|
|
|
|
// Analogous to Rust's Never type
|
|
//TODO: clang fails to compile C with [[noreturn]]
|
|
#if defined(__cplusplus) && __HAS_ATTRIBUTE(noreturn) && !(__clang__)
|
|
#define __noreturn [[noreturn]]
|
|
// #elif __STDC_VERSION__ >= 201112L
|
|
// FIXME: cbindgen incorrectly places _Noreturn
|
|
// #define __noreturn _Noreturn
|
|
#elif defined(__GNUC__)
|
|
#define __noreturn __attribute__((__noreturn__))
|
|
#else
|
|
#define __noreturn
|
|
#endif
|
|
|
|
// Analogous to Rust's #[must_use]
|
|
// C23 only
|
|
#if __HAS_ATTRIBUTE(nodiscard)
|
|
#define __nodiscard [[nodiscard]]
|
|
#define __nodiscardNote(x) [[nodiscard(x)]]
|
|
#else
|
|
#define __nodiscard
|
|
#define __nodiscardNote(x)
|
|
#endif
|
|
|
|
// Analogous to Rust's #[deprecated]
|
|
// C23 only
|
|
#if __HAS_ATTRIBUTE(deprecated)
|
|
#define __deprecated [[deprecated]]
|
|
#define __deprecatedNote(x) [[deprecated(x)]]
|
|
#else
|
|
#define __deprecated
|
|
#define __deprecatedNote(x)
|
|
#endif
|
|
|
|
#endif
|