From: Owen Shepherd Date: Wed, 26 Dec 2012 18:51:35 +0000 (+0000) Subject: _PDCLIB_aux.h: Better detection of Clang and GCC features X-Git-Url: https://pd.if.org/git/?p=pdclib;a=commitdiff_plain;h=28f6edc984f962ed33ac4fb505cf94b3e78f3f6d _PDCLIB_aux.h: Better detection of Clang and GCC features --- diff --git a/internals/_PDCLIB_aux.h b/internals/_PDCLIB_aux.h index 986807e..bc13897 100644 --- a/internals/_PDCLIB_aux.h +++ b/internals/_PDCLIB_aux.h @@ -51,6 +51,80 @@ #error Unsupported _ _cplusplus (__cplusplus) (supported: ISO/IEC 14882:1997, ISO/IEC 14882:2011). #endif +#ifndef __STDC_HOSTED__ + #error Compiler does not define _ _STDC_HOSTED_ _ (not standard-compliant)! +#elif __STDC_HOSTED__ == 0 + #define _PDCLIB_HOSTED 0 +#elif __STDC_HOSTED__ == 1 + #define _PDCLIB_HOSTED 1 +#else + #error Compiler does not define _ _STDC_HOSTED_ _ to 0 or 1 (not standard-compliant)! +#endif + +#ifdef __cplusplus + #define _PDCLIB_BEGIN_EXTERN_C extern "C" { + #define _PDCLIB_END_EXTERN_C } + typedef bool _PDCLIB_bool; +#else + #define _PDCLIB_BEGIN_EXTERN_C + #define _PDCLIB_END_EXTERN_C + typedef _Bool _PDCLIB_bool; +#endif + +/* Clang style feature detection macros + * Note: It is common to #define __has_feature(0) if undefined so the presence + * of this macro does not guarantee it to be working + */ + +#ifdef __has_feature + #define _PDCLIB_HAS_FEATURE(x) __has_feature(x) +#else + #define _PDCLIB_HAS_FEATURE(x) (0) +#endif + +#ifdef __has_extension + #define _PDCLIB_HAS_EXTENSION(x) __has_extension(x) +#else + // Older versions of Clang use __has_feature instead + #define _PDCLIB_HAS_EXTENSION(x) _PDCLIB_HAS_FEATURE(x) +#endif + +#ifdef __has_builtin + #define _PDCLIB_HAS_BUILTIN(x) __has_builtin(x) +#else + #define _PDCLIB_HAS_BUILTIN(x) (0) +#endif + +#ifdef __has_attribute + #define _PDCLIB_HAS_ATTRIBUTE(x) __has_builtin(x) +#else + #define _PDCLIB_HAS_ATTRIBUTE(x) (0) +#endif + +/* GCC feature detection macros */ + +#if defined(__GNUC__) + #define _PDCLIB_GCC_MIN(maj, min) \ + ((__GNUC__ > maj) || (__GNUC__ == maj && __GNUC_MINOR__ >= min)) +#else + #define _PDCLIB_GCC_MIN(maj, min) (0) +#endif + +/* Hybrid GCC/Clang feature detection macros */ +#define _PDCLIB_GCC_FEATURE(x, gccmaj, gccmin) \ + (_PDCLIB_HAS_FEATURE(x) || _PDCLIB_GCC_MIN(gccmin, gccmaj)) + +#define _PDCLIB_GCC_EXTENSION(x, gccmaj, gccmin) \ + (_PDCLIB_HAS_EXTENSION(x) || _PDCLIB_GCC_MIN(gccmin, gccmaj)) + +#define _PDCLIB_GCC_BUILTIN(x, gccmaj, gccmin) \ + (_PDCLIB_HAS_BUILTIN(x) || _PDCLIB_GCC_MIN(gccmin, gccmaj)) + +#define _PDCLIB_GCC_ATTRIBUTE(x, gccmaj, gccmin) \ + (_PDCLIB_HAS_ATTRIBUTE(x) || _PDCLIB_GCC_MIN(gccmin, gccmaj)) + +/* Extension & Language feature detection */ + #if _PDCLIB_C_VERSION >= 1999 || defined(__cplusplus) #ifndef __cplusplus #define _PDCLIB_restrict restrict @@ -66,10 +140,9 @@ #define _PDCLIB_noexcept #endif -#if _PDCLIB_CXX_VERSION >= 2011 - // Hold off on C++ attribute syntax for now - // #define _PDCLIB_noreturn [[noreturn]] -#elif _PDCLIB_C_VERSION >= 2011 +#if _PDCLIB_CXX_VERSION >= 2011 && _PDCLIB_GCC_FEATURE(cxx_attributes, 4, 8) + #define _PDCLIB_noreturn [[noreturn]] +#elif _PDCLIB_C_VERSION >= 2011 && _PDCLIB_GCC_FEATURE(c_noreturn, 4, 7) #define _PDCLIB_noreturn _Noreturn #endif @@ -78,42 +151,38 @@ #define _PDCLIB_IMPORT __declspec(dllimport) #endif -#ifdef __GNUC__ - #ifndef _PDCLIB_EXPORT - #define _PDCLIB_EXPORT __attribute__((__visibility__("protected"))) - #endif - - #ifndef _PDCLIB_IMPORT - #define _PDCLIB_IMPORT - #endif +#if !defined(_PDCLIB_EXPORT) && _PDCLIB_GCC_ATTRIBUTE(__visibility__, 4, 0) + #define _PDCLIB_EXPORT __attribute__((__visibility__("protected"))) +#endif - #ifndef _PDCLIB_HIDDEN - #define _PDCLIB_HIDDEN __attribute__((__visibility__("hidden"))) - #endif +#if !defined(_PDCLIB_HIDDEN) && _PDCLIB_GCC_ATTRIBUTE(__visibility__, 4, 0) + #define _PDCLIB_HIDDEN __attribute__((__visibility__("hidden"))) +#endif - #ifndef _PDCLIB_nothrow - #define _PDCLIB_nothrow __attribute__((__nothrow__)) - #define _PDCLIB_noexcept - #endif +#if !defined(_PDCLIB_nothrow) && _PDCLIB_GCC_ATTRIBUTE(__nothrow__, 4, 0) + #define _PDCLIB_nothrow __attribute__((__nothrow__)) + #define _PDCLIB_noexcept +#endif - #ifndef _PDCLIB_restrict - #define _PDCLIB_restrict __restrict - #endif +#if !defined(_PDCLIB_restrict) && _PDCLIB_GCC_MIN(3, 0) + #define _PDCLIB_restrict __restrict +#endif - #ifndef _PDCLIB_inline - #define _PDCLIB_inline __inline - #endif +#if !defined(_PDCLIB_inline) && _PDCLIB_GCC_MIN(3, 0) + #define _PDCLIB_inline __inline +#endif - #ifndef _PDCLIB_noreturn +#if !defined(_PDCLIB_noreturn) && _PDCLIB_GCC_ATTRIBUTE(__noreturn__, 3, 0) /* If you don't use __noreturn__, then stdnoreturn.h will break things! */ - #define _PDCLIB_noreturn __attribute__((__noreturn__)) - #endif + #define _PDCLIB_noreturn __attribute__((__noreturn__)) +#endif - #ifndef _PDCLIB_DEPRECATED - #define _PDCLIB_DEPRECATED __attribute__ ((deprecated)) - #endif +#if !defined(_PDCLIB_DEPRECATED) && _PDCLIB_GCC_ATTRIBUTE(__deprecated__, 3, 0) + #define _PDCLIB_DEPRECATED __attribute__ ((__deprecated__)) #endif +/* No-op fallbacks */ + #ifndef _PDCLIB_nothrow #define _PDCLIB_nothrow #define _PDCLIB_noexcept @@ -155,26 +224,6 @@ #define _PDCLIB_DEPRECATED #endif -#ifndef __STDC_HOSTED__ -#error Compiler does not define _ _STDC_HOSTED_ _ (not standard-compliant)! -#elif __STDC_HOSTED__ == 0 -#define _PDCLIB_HOSTED 0 -#elif __STDC_HOSTED__ == 1 -#define _PDCLIB_HOSTED 1 -#else -#error Compiler does not define _ _STDC_HOSTED_ _ to 0 or 1 (not standard-compliant)! -#endif - -#ifdef __cplusplus - #define _PDCLIB_BEGIN_EXTERN_C extern "C" { - #define _PDCLIB_END_EXTERN_C } - typedef bool _PDCLIB_bool; -#else - #define _PDCLIB_BEGIN_EXTERN_C - #define _PDCLIB_END_EXTERN_C - typedef _Bool _PDCLIB_bool; -#endif - /*#if _PDCLIB_C_VERSION != 1999 #error PDCLib might not be fully conforming to either C89 or C95 prior to v2.x. #endif*/