1228753Smm/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ 2228753Smm/* 3228753Smm * Copyright (c) 1993, 1994, 1995, 1996, 1997 4228753Smm * The Regents of the University of California. All rights reserved. 5228753Smm * 6228753Smm * Redistribution and use in source and binary forms, with or without 7228753Smm * modification, are permitted provided that the following conditions 8228753Smm * are met: 9228753Smm * 1. Redistributions of source code must retain the above copyright 10228753Smm * notice, this list of conditions and the following disclaimer. 11228753Smm * 2. Redistributions in binary form must reproduce the above copyright 12228753Smm * notice, this list of conditions and the following disclaimer in the 13228753Smm * documentation and/or other materials provided with the distribution. 14228753Smm * 3. All advertising materials mentioning features or use of this software 15228753Smm * must display the following acknowledgement: 16228753Smm * This product includes software developed by the Computer Systems 17228753Smm * Engineering Group at Lawrence Berkeley Laboratory. 18228753Smm * 4. Neither the name of the University nor of the Laboratory may be used 19228753Smm * to endorse or promote products derived from this software without 20228753Smm * specific prior written permission. 21228753Smm * 22228753Smm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23228753Smm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24228753Smm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25229592Smm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26228753Smm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27228753Smm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28228753Smm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29228753Smm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30228753Smm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31228753Smm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32228753Smm * SUCH DAMAGE. 33228753Smm */ 34228753Smm 35228753Smm#ifndef nd_compiler_tests_h 36228753Smm#define nd_compiler_tests_h 37228753Smm 38228753Smm/* 39228753Smm * This was introduced by Clang: 40228753Smm * 41228753Smm * https://clang.llvm.org/docs/LanguageExtensions.html#has-attribute 42228753Smm * 43228753Smm * in some version (which version?); it has been picked up by GCC 5.0. 44228753Smm */ 45228753Smm#ifndef __has_attribute 46228753Smm /* 47228753Smm * It's a macro, so you can check whether it's defined to check 48228753Smm * whether it's supported. 49228753Smm * 50228753Smm * If it's not, define it to always return 0, so that we move on to 51228753Smm * the fallback checks. 52228753Smm */ 53228753Smm #define __has_attribute(x) 0 54228753Smm#endif 55228753Smm 56228753Smm/* 57228753Smm * Note that the C90 spec's "6.8.1 Conditional inclusion" and the 58228753Smm * C99 spec's and C11 spec's "6.10.1 Conditional inclusion" say: 59228753Smm * 60228753Smm * Prior to evaluation, macro invocations in the list of preprocessing 61228753Smm * tokens that will become the controlling constant expression are 62228753Smm * replaced (except for those macro names modified by the defined unary 63228753Smm * operator), just as in normal text. If the token "defined" is 64228753Smm * generated as a result of this replacement process or use of the 65228753Smm * "defined" unary operator does not match one of the two specified 66228753Smm * forms prior to macro replacement, the behavior is undefined. 67228753Smm * 68228753Smm * so you shouldn't use defined() in a #define that's used in #if or 69228753Smm * #elif. Some versions of Clang, for example, will warn about this. 70228753Smm * 71228753Smm * Instead, we check whether the pre-defined macros for particular 72228753Smm * compilers are defined and, if not, define the "is this version XXX 73228753Smm * or a later version of this compiler" macros as 0. 74228753Smm */ 75228753Smm 76228753Smm/* 77228753Smm * Check whether this is GCC major.minor or a later release, or some 78228753Smm * compiler that claims to be "just like GCC" of that version or a 79228753Smm * later release. 80228753Smm */ 81228753Smm 82228753Smm#if ! defined(__GNUC__) 83228753Smm /* Not GCC and not "just like GCC" */ 84228753Smm #define ND_IS_AT_LEAST_GNUC_VERSION(major, minor) 0 85228753Smm#else 86228753Smm /* GCC or "just like GCC" */ 87228753Smm #define ND_IS_AT_LEAST_GNUC_VERSION(major, minor) \ 88228753Smm (__GNUC__ > (major) || \ 89228753Smm (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor))) 90228753Smm#endif 91228753Smm 92228753Smm/* 93228753Smm * Check whether this is Clang major.minor or a later release. 94228753Smm */ 95228753Smm 96228753Smm#if !defined(__clang__) 97228753Smm /* Not Clang */ 98228753Smm #define ND_IS_AT_LEAST_CLANG_VERSION(major, minor) 0 99228753Smm#else 100228753Smm /* Clang */ 101228753Smm #define ND_IS_AT_LEAST_CLANG_VERSION(major, minor) \ 102228753Smm (__clang_major__ > (major) || \ 103228753Smm (__clang_major__ == (major) && __clang_minor__ >= (minor))) 104228753Smm#endif 105228753Smm 106228753Smm/* 107228753Smm * Check whether this is Sun C/SunPro C/Oracle Studio major.minor 108228753Smm * or a later release. 109228753Smm * 110228753Smm * The version number in __SUNPRO_C is encoded in hex BCD, with the 111228753Smm * uppermost hex digit being the major version number, the next 112228753Smm * one or two hex digits being the minor version number, and 113228753Smm * the last digit being the patch version. 114228753Smm * 115228753Smm * It represents the *compiler* version, not the product version; 116228753Smm * see 117228753Smm * 118228753Smm * https://sourceforge.net/p/predef/wiki/Compilers/ 119228753Smm * 120228753Smm * for a partial mapping, which we assume continues for later 121228753Smm * 12.x product releases. 122228753Smm */ 123228753Smm 124228753Smm#if ! defined(__SUNPRO_C) 125228753Smm /* Not Sun/Oracle C */ 126228753Smm #define ND_IS_AT_LEAST_SUNC_VERSION(major,minor) 0 127228753Smm#else 128228753Smm /* Sun/Oracle C */ 129228753Smm #define ND_SUNPRO_VERSION_TO_BCD(major, minor) \ 130228753Smm (((minor) >= 10) ? \ 131228753Smm (((major) << 12) | (((minor)/10) << 8) | (((minor)%10) << 4)) : \ 132228753Smm (((major) << 8) | ((minor) << 4))) 133228753Smm #define ND_IS_AT_LEAST_SUNC_VERSION(major,minor) \ 134228753Smm (__SUNPRO_C >= ND_SUNPRO_VERSION_TO_BCD((major), (minor))) 135228753Smm#endif 136228753Smm 137228753Smm/* 138228753Smm * Check whether this is IBM XL C major.minor or a later release. 139228753Smm * 140228753Smm * The version number in __xlC__ has the major version in the 141228753Smm * 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