1 /* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ 2 /* 3 * Copyright (c) 1993, 1994, 1995, 1996, 1997 4 * The Regents of the University of California. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by the Computer Systems 17 * Engineering Group at Lawrence Berkeley Laboratory. 18 * 4. Neither the name of the University nor of the Laboratory may be used 19 * to endorse or promote products derived from this software without 20 * specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #ifndef nd_compiler_tests_h 36 #define nd_compiler_tests_h 37 38 /* 39 * This was introduced by Clang: 40 * 41 * https://clang.llvm.org/docs/LanguageExtensions.html#has-attribute 42 * 43 * in some version (which version?); it has been picked up by GCC 5.0. 44 */ 45 #ifndef __has_attribute 46 /* 47 * It's a macro, so you can check whether it's defined to check 48 * whether it's supported. 49 * 50 * If it's not, define it to always return 0, so that we move on to 51 * the fallback checks. 52 */ 53 #define __has_attribute(x) 0 54 #endif 55 56 /* 57 * Note that the C90 spec's "6.8.1 Conditional inclusion" and the 58 * C99 spec's and C11 spec's "6.10.1 Conditional inclusion" say: 59 * 60 * Prior to evaluation, macro invocations in the list of preprocessing 61 * tokens that will become the controlling constant expression are 62 * replaced (except for those macro names modified by the defined unary 63 * operator), just as in normal text. If the token "defined" is 64 * generated as a result of this replacement process or use of the 65 * "defined" unary operator does not match one of the two specified 66 * forms prior to macro replacement, the behavior is undefined. 67 * 68 * so you shouldn't use defined() in a #define that's used in #if or 69 * #elif. Some versions of Clang, for example, will warn about this. 70 * 71 * Instead, we check whether the pre-defined macros for particular 72 * compilers are defined and, if not, define the "is this version XXX 73 * or a later version of this compiler" macros as 0. 74 */ 75 76 /* 77 * Check whether this is GCC major.minor or a later release, or some 78 * compiler that claims to be "just like GCC" of that version or a 79 * later release. 80 */ 81 82 #if ! defined(__GNUC__) 83 /* Not GCC and not "just like GCC" */ 84 #define ND_IS_AT_LEAST_GNUC_VERSION(major, minor) 0 85 #else 86 /* GCC or "just like GCC" */ 87 #define ND_IS_AT_LEAST_GNUC_VERSION(major, minor) \ 88 (__GNUC__ > (major) || \ 89 (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor))) 90 #endif 91 92 /* 93 * Check whether this is Clang major.minor or a later release. 94 */ 95 96 #if !defined(__clang__) 97 /* Not Clang */ 98 #define ND_IS_AT_LEAST_CLANG_VERSION(major, minor) 0 99 #else 100 /* Clang */ 101 #define ND_IS_AT_LEAST_CLANG_VERSION(major, minor) \ 102 (__clang_major__ > (major) || \ 103 (__clang_major__ == (major) && __clang_minor__ >= (minor))) 104 #endif 105 106 /* 107 * Check whether this is Sun C/SunPro C/Oracle Studio major.minor 108 * or a later release. 109 * 110 * The version number in __SUNPRO_C is encoded in hex BCD, with the 111 * uppermost hex digit being the major version number, the next 112 * one or two hex digits being the minor version number, and 113 * the last digit being the patch version. 114 * 115 * It represents the *compiler* version, not the product version; 116 * see 117 * 118 * https://sourceforge.net/p/predef/wiki/Compilers/ 119 * 120 * for a partial mapping, which we assume continues for later 121 * 12.x product releases. 122 */ 123 124 #if ! defined(__SUNPRO_C) 125 /* Not Sun/Oracle C */ 126 #define ND_IS_AT_LEAST_SUNC_VERSION(major,minor) 0 127 #else 128 /* Sun/Oracle C */ 129 #define ND_SUNPRO_VERSION_TO_BCD(major, minor) \ 130 (((minor) >= 10) ? \ 131 (((major) << 12) | (((minor)/10) << 8) | (((minor)%10) << 4)) : \ 132 (((major) << 8) | ((minor) << 4))) 133 #define ND_IS_AT_LEAST_SUNC_VERSION(major,minor) \ 134 (__SUNPRO_C >= ND_SUNPRO_VERSION_TO_BCD((major), (minor))) 135 #endif 136 137 /* 138 * Check whether this is IBM XL C major.minor or a later release. 139 * 140 * The version number in __xlC__ has the major version in the 141 * upper 8 bits and the minor version in the lower 8 bits. 142 * On AIX __xlC__ is always defined, __ibmxl__ becomes defined in XL C 16.1. 143 * On Linux since XL C 13.1.6 __xlC__ is not defined by default anymore, but 144 * __ibmxl__ is defined since at least XL C 13.1.1. 145 */ 146 147 #if ! defined(__xlC__) && ! defined(__ibmxl__) 148 /* Not XL C */ 149 #define ND_IS_AT_LEAST_XL_C_VERSION(major,minor) 0 150 #define ND_IS_AT_LEAST_XL_C_MODFIX(modification, fixlevel) 0 151 #else 152 /* XL C */ 153 #if defined(__ibmxl__) 154 /* 155 * Later Linux version of XL C; use __ibmxl_version__ to test 156 * the version. 157 */ 158 #define ND_IS_AT_LEAST_XL_C_VERSION(major, minor) \ 159 (__ibmxl_version__ > (major) || \ 160 (__ibmxl_version__ == (major) && __ibmxl_release__ >= (minor))) 161 #define ND_IS_AT_LEAST_XL_C_MODFIX(modification, fixlevel) \ 162 (__ibmxl_modification__ > (modification) || \ 163 (__ibmxl_modification__ == (modification) && \ 164 __ibmxl_ptf_fix_level__ >= (fixlevel))) 165 #else /* __ibmxl__ */ 166 /* 167 * __ibmxl__ not defined; use __xlC__ to test the version. 168 */ 169 #define ND_IS_AT_LEAST_XL_C_VERSION(major, minor) \ 170 (__xlC__ >= (((major) << 8) | (minor))) 171 #define ND_IS_AT_LEAST_XL_C_MODFIX(modification, fixlevel) \ 172 ((((modification) << 8) | (fixlevel)) >= __xlC_ver__) 173 #endif /* __ibmxl__ */ 174 #endif 175 176 /* 177 * Check whether this is HP aC++/HP C major.minor or a later release. 178 * 179 * The version number in __HP_aCC is encoded in zero-padded decimal BCD, 180 * with the "A." stripped off, the uppermost two decimal digits being 181 * the major version number, the next two decimal digits being the minor 182 * version number, and the last two decimal digits being the patch version. 183 * (Strip off the A., remove the . between the major and minor version 184 * number, and add two digits of patch.) 185 */ 186 187 #if ! defined(__HP_aCC) 188 /* Not HP C */ 189 #define ND_IS_AT_LEAST_HP_C_VERSION(major,minor) 0 190 #else 191 /* HP C */ 192 #define ND_IS_AT_LEAST_HP_C_VERSION(major,minor) \ 193 (__HP_aCC >= ((major)*10000 + (minor)*100)) 194 #endif 195 196 #endif /* nd_funcattrs_h */ 197