X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=src%2Finclude%2Fc.h;h=9066e3c57835f97f8a0ee6cf1cf4bd8102979fcb;hb=c7b8998ebbf310a156aa38022555a24d98fdbfb4;hp=ce38d78736f5ae275a9186ccaf209786c4b77bcf;hpb=b64d92f1a5602c55ee8b27a7ac474f03b7aee340;p=postgresql diff --git a/src/include/c.h b/src/include/c.h index ce38d78736..9066e3c578 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -9,7 +9,7 @@ * polluting the namespace with lots of stuff... * * - * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/c.h @@ -62,7 +62,7 @@ #define WIN32 #endif -#if !defined(WIN32) && !defined(__CYGWIN__) /* win32 includes further down */ +#if !defined(WIN32) && !defined(__CYGWIN__) /* win32 includes further down */ #include "pg_config_os.h" /* must be before any system header files */ #endif @@ -101,6 +101,19 @@ #include "pg_config_os.h" #endif +/* + * Force disable inlining if PG_FORCE_DISABLE_INLINE is defined. This is used + * to work around compiler bugs and might also be useful for investigatory + * purposes by defining the symbol in the platform's header.. + * + * This is done early (in slightly the wrong section) as functionality later + * in this file might want to rely on inline functions. + */ +#ifdef PG_FORCE_DISABLE_INLINE +#undef inline +#define inline +#endif + /* Must be before gettext() games below */ #include @@ -136,6 +149,8 @@ /* * CppAsString * Convert the argument to a string, using the C preprocessor. + * CppAsString2 + * Convert the argument to a string, after one round of macro expansion. * CppConcat * Concatenate two arguments together, using the C preprocessor. * @@ -144,6 +159,7 @@ * backward compatibility with existing PostgreSQL code. */ #define CppAsString(identifier) #identifier +#define CppAsString2(x) CppAsString(x) #define CppConcat(x, y) x##y /* @@ -156,8 +172,15 @@ #define dummyret char #endif -#ifndef __GNUC__ -#define __attribute__(_arg_) +/* Which __func__ symbol do we have, if any? */ +#ifdef HAVE_FUNCNAME__FUNC +#define PG_FUNCNAME_MACRO __func__ +#else +#ifdef HAVE_FUNCNAME__FUNCTION +#define PG_FUNCNAME_MACRO __FUNCTION__ +#else +#define PG_FUNCNAME_MACRO NULL +#endif #endif /* ---------------------------------------------------------------- @@ -186,7 +209,7 @@ typedef char bool; #ifndef false #define false ((bool) 0) #endif -#endif /* not C++ */ +#endif /* not C++ */ typedef bool *BoolPtr; @@ -231,7 +254,7 @@ typedef char *Pointer; typedef signed char int8; /* == 8 bits */ typedef signed short int16; /* == 16 bits */ typedef signed int int32; /* == 32 bits */ -#endif /* not HAVE_INT8 */ +#endif /* not HAVE_INT8 */ /* * uintN @@ -243,7 +266,7 @@ typedef signed int int32; /* == 32 bits */ typedef unsigned char uint8; /* == 8 bits */ typedef unsigned short uint16; /* == 16 bits */ typedef unsigned int uint32; /* == 32 bits */ -#endif /* not HAVE_UINT8 */ +#endif /* not HAVE_UINT8 */ /* * bitsN @@ -292,15 +315,39 @@ typedef unsigned long long int uint64; #define INT64_FORMAT "%" INT64_MODIFIER "d" #define UINT64_FORMAT "%" INT64_MODIFIER "u" -/* Select timestamp representation (float8 or int64) */ -#ifdef USE_INTEGER_DATETIMES -#define HAVE_INT64_TIMESTAMP +/* + * 128-bit signed and unsigned integers + * There currently is only a limited support for the type. E.g. 128bit + * literals and snprintf are not supported; but math is. + */ +#if defined(PG_INT128_TYPE) +#define HAVE_INT128 +typedef PG_INT128_TYPE int128; +typedef unsigned PG_INT128_TYPE uint128; #endif -/* sig_atomic_t is required by ANSI C, but may be missing on old platforms */ -#ifndef HAVE_SIG_ATOMIC_T -typedef int sig_atomic_t; -#endif +/* + * stdint.h limits aren't guaranteed to be present and aren't guaranteed to + * have compatible types with our fixed width types. So just define our own. + */ +#define PG_INT8_MIN (-0x7F-1) +#define PG_INT8_MAX (0x7F) +#define PG_UINT8_MAX (0xFF) +#define PG_INT16_MIN (-0x7FFF-1) +#define PG_INT16_MAX (0x7FFF) +#define PG_UINT16_MAX (0xFFFF) +#define PG_INT32_MIN (-0x7FFFFFFF-1) +#define PG_INT32_MAX (0x7FFFFFFF) +#define PG_UINT32_MAX (0xFFFFFFFF) +#define PG_INT64_MIN (-INT64CONST(0x7FFFFFFFFFFFFFFF) - 1) +#define PG_INT64_MAX INT64CONST(0x7FFFFFFFFFFFFFFF) +#define PG_UINT64_MAX UINT64CONST(0xFFFFFFFFFFFFFFFF) + +/* + * We now always use int64 timestamps, but keep this symbol defined for the + * benefit of external code that might test it. + */ +#define HAVE_INT64_TIMESTAMP /* * Size @@ -373,7 +420,7 @@ typedef uint32 CommandId; typedef struct { int indx[MAXDIM]; -} IntArray; +} IntArray; /* ---------------- * Variable-length datatypes all share the 'struct varlena' header. @@ -382,16 +429,17 @@ typedef struct * may be compressed or moved out-of-line. However datatype-specific routines * are mostly content to deal with de-TOASTed values only, and of course * client-side routines should never see a TOASTed value. But even in a - * de-TOASTed value, beware of touching vl_len_ directly, as its representation - * is no longer convenient. It's recommended that code always use the VARDATA, - * VARSIZE, and SET_VARSIZE macros instead of relying on direct mentions of - * the struct fields. See postgres.h for details of the TOASTed form. + * de-TOASTed value, beware of touching vl_len_ directly, as its + * representation is no longer convenient. It's recommended that code always + * use macros VARDATA_ANY, VARSIZE_ANY, VARSIZE_ANY_EXHDR, VARDATA, VARSIZE, + * and SET_VARSIZE instead of relying on direct mentions of the struct fields. + * See postgres.h for details of the TOASTed form. * ---------------- */ struct varlena { char vl_len_[4]; /* Do not touch this field directly! */ - char vl_dat[1]; + char vl_dat[FLEXIBLE_ARRAY_MEMBER]; /* Data content is here */ }; #define VARHDRSZ ((int32) sizeof(int32)) @@ -399,7 +447,7 @@ struct varlena /* * These widely-used datatypes are just a varlena header and the data bytes. * There is no terminating null or anything like that --- the data length is - * always VARSIZE(ptr) - VARHDRSZ. + * always VARSIZE_ANY_EXHDR(ptr). */ typedef struct varlena bytea; typedef struct varlena text; @@ -424,8 +472,8 @@ typedef struct Oid elemtype; int dim1; int lbound1; - int16 values[1]; /* VARIABLE LENGTH ARRAY */ -} int2vector; /* VARIABLE LENGTH STRUCT */ + int16 values[FLEXIBLE_ARRAY_MEMBER]; +} int2vector; typedef struct { @@ -435,8 +483,8 @@ typedef struct Oid elemtype; int dim1; int lbound1; - Oid values[1]; /* VARIABLE LENGTH ARRAY */ -} oidvector; /* VARIABLE LENGTH STRUCT */ + Oid values[FLEXIBLE_ARRAY_MEMBER]; +} oidvector; /* * Representation of a Name: effectively just a C string, but null-padded to @@ -484,6 +532,9 @@ typedef NameData *Name; #define PointerIsAligned(pointer, type) \ (((uintptr_t)(pointer) % (sizeof (type))) == 0) +#define OffsetToPointer(base, offset) \ + ((void *)((char *) base + offset)) + #define OidIsValid(objectId) ((bool) ((objectId) != InvalidOid)) #define RegProcedureIsValid(p) OidIsValid(p) @@ -502,7 +553,7 @@ typedef NameData *Name; */ #ifndef offsetof #define offsetof(type, field) ((long) &((type *)0)->field) -#endif /* offsetof */ +#endif /* offsetof */ /* * lengthof @@ -537,6 +588,7 @@ typedef NameData *Name; #define MAXALIGN(LEN) TYPEALIGN(MAXIMUM_ALIGNOF, (LEN)) /* MAXALIGN covers only built-in types, not buffers */ #define BUFFERALIGN(LEN) TYPEALIGN(ALIGNOF_BUFFER, (LEN)) +#define CACHELINEALIGN(LEN) TYPEALIGN(PG_CACHE_LINE_SIZE, (LEN)) #define TYPEALIGN_DOWN(ALIGNVAL,LEN) \ (((uintptr_t) (LEN)) & ~((uintptr_t) ((ALIGNVAL) - 1))) @@ -559,6 +611,48 @@ typedef NameData *Name; /* we don't currently need wider versions of the other ALIGN macros */ #define MAXALIGN64(LEN) TYPEALIGN64(MAXIMUM_ALIGNOF, (LEN)) +/* ---------------- + * Attribute macros + * + * GCC: https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html + * GCC: https://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html + * Sunpro: https://docs.oracle.com/cd/E18659_01/html/821-1384/gjzke.html + * XLC: http://www-01.ibm.com/support/knowledgecenter/SSGH2K_11.1.0/com.ibm.xlc111.aix.doc/language_ref/function_attributes.html + * XLC: http://www-01.ibm.com/support/knowledgecenter/SSGH2K_11.1.0/com.ibm.xlc111.aix.doc/language_ref/type_attrib.html + * ---------------- + */ + +/* only GCC supports the unused attribute */ +#ifdef __GNUC__ +#define pg_attribute_unused() __attribute__((unused)) +#else +#define pg_attribute_unused() +#endif + +/* GCC and XLC support format attributes */ +#if defined(__GNUC__) || defined(__IBMC__) +#define pg_attribute_format_arg(a) __attribute__((format_arg(a))) +#define pg_attribute_printf(f,a) __attribute__((format(PG_PRINTF_ATTRIBUTE, f, a))) +#else +#define pg_attribute_format_arg(a) +#define pg_attribute_printf(f,a) +#endif + +/* GCC, Sunpro and XLC support aligned, packed and noreturn */ +#if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__) +#define pg_attribute_aligned(a) __attribute__((aligned(a))) +#define pg_attribute_noreturn() __attribute__((noreturn)) +#define pg_attribute_packed() __attribute__((packed)) +#define HAVE_PG_ATTRIBUTE_NORETURN 1 +#else +/* + * NB: aligned and packed are not given default definitions because they + * affect code functionality; they *must* be implemented by the compiler + * if they are to be used. + */ +#define pg_attribute_noreturn() +#endif + /* ---------------------------------------------------------------- * Section 6: assertions * ---------------------------------------------------------------- @@ -578,12 +672,12 @@ typedef NameData *Name; */ #ifndef USE_ASSERT_CHECKING -#define Assert(condition) +#define Assert(condition) ((void)true) #define AssertMacro(condition) ((void)true) -#define AssertArg(condition) -#define AssertState(condition) +#define AssertArg(condition) ((void)true) +#define AssertState(condition) ((void)true) #define AssertPointerAlignment(ptr, bndr) ((void)true) -#define Trap(condition, errorType) +#define Trap(condition, errorType) ((void)true) #define TrapMacro(condition, errorType) (true) #elif defined(FRONTEND) @@ -638,7 +732,7 @@ typedef NameData *Name; Trap(TYPEALIGN(bndr, (uintptr_t)(ptr)) != (uintptr_t)(ptr), \ "UnalignedPointer") -#endif /* USE_ASSERT_CHECKING && !FRONTEND */ +#endif /* USE_ASSERT_CHECKING && !FRONTEND */ /* * Macros to support compile-time assertion checks. @@ -664,7 +758,7 @@ typedef NameData *Name; ((void) sizeof(struct { int static_assert_failure : (condition) ? 1 : -1; })) #define StaticAssertExpr(condition, errmessage) \ StaticAssertStmt(condition, errmessage) -#endif /* HAVE__STATIC_ASSERT */ +#endif /* HAVE__STATIC_ASSERT */ /* @@ -692,7 +786,7 @@ typedef NameData *Name; #define AssertVariableIsOfTypeMacro(varname, typename) \ ((void) StaticAssertExpr(sizeof(varname) == sizeof(typename), \ CppAsString(varname) " does not have type " CppAsString(typename))) -#endif /* HAVE__BUILTIN_TYPES_COMPATIBLE_P */ +#endif /* HAVE__BUILTIN_TYPES_COMPATIBLE_P */ /* ---------------------------------------------------------------- @@ -854,31 +948,19 @@ typedef NameData *Name; /* - * Function inlining support -- Allow modules to define functions that may be - * inlined, if the compiler supports it. + * Hints to the compiler about the likelihood of a branch. Both likely() and + * unlikely() return the boolean value of the contained expression. * - * The function bodies must be defined in the module header prefixed by - * STATIC_IF_INLINE, protected by a cpp symbol that the module's .c file must - * define. If the compiler doesn't support inline functions, the function - * definitions are pulled in by the .c file as regular (not inline) symbols. - * - * The header must also declare the functions' prototypes, protected by - * !PG_USE_INLINE. + * These should only be used sparingly, in very hot code paths. It's very easy + * to mis-estimate likelihoods. */ - -/* declarations which are only visible when not inlining and in the .c file */ -#ifdef PG_USE_INLINE -#define STATIC_IF_INLINE static inline +#if __GNUC__ >= 3 +#define likely(x) __builtin_expect((x) != 0, 1) +#define unlikely(x) __builtin_expect((x) != 0, 0) #else -#define STATIC_IF_INLINE -#endif /* PG_USE_INLINE */ - -/* declarations which are marked inline when inlining, extern otherwise */ -#ifdef PG_USE_INLINE -#define STATIC_IF_INLINE_DECLARE static inline -#else -#define STATIC_IF_INLINE_DECLARE extern -#endif /* PG_USE_INLINE */ +#define likely(x) ((x) != 0) +#define unlikely(x) ((x) != 0) +#endif /* ---------------------------------------------------------------- @@ -905,17 +987,17 @@ typedef NameData *Name; #ifdef USE_ASSERT_CHECKING #define PG_USED_FOR_ASSERTS_ONLY #else -#define PG_USED_FOR_ASSERTS_ONLY __attribute__((unused)) +#define PG_USED_FOR_ASSERTS_ONLY pg_attribute_unused() #endif /* gettext domain name mangling */ /* - * To better support parallel installations of major PostgeSQL + * To better support parallel installations of major PostgreSQL * versions as well as parallel installations of major library soname * versions, we mangle the gettext domain name by appending those - * version numbers. The coding rule ought to be that whereever the + * version numbers. The coding rule ought to be that wherever the * domain name is mentioned as a literal, it must be wrapped into * PG_TEXTDOMAIN(). The macros below do not work on non-literals; but * that is somewhat intentional because it avoids having to worry @@ -924,10 +1006,6 @@ typedef NameData *Name; * * Make sure this matches the installation rules in nls-global.mk. */ - -/* need a second indirection because we want to stringize the macro value, not the name */ -#define CppAsString2(x) CppAsString(x) - #ifdef SO_MAJOR_VERSION #define PG_TEXTDOMAIN(domain) (domain CppAsString2(SO_MAJOR_VERSION) "-" PG_MAJORVERSION) #else @@ -969,10 +1047,7 @@ typedef NameData *Name; */ #if !HAVE_DECL_SNPRINTF -extern int -snprintf(char *str, size_t count, const char *fmt,...) -/* This extension allows gcc to check the format string */ -__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4))); +extern int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3, 4); #endif #if !HAVE_DECL_VSNPRINTF @@ -1007,9 +1082,9 @@ extern int vsnprintf(char *str, size_t count, const char *fmt, va_list args); /* * When there is no sigsetjmp, its functionality is provided by plain * setjmp. Incidentally, nothing provides setjmp's functionality in - * that case. + * that case. We now support the case only on Windows. */ -#ifndef HAVE_SIGSETJMP +#ifdef WIN32 #define sigjmp_buf jmp_buf #define sigsetjmp(x,y) setjmp(x) #define siglongjmp longjmp @@ -1049,4 +1124,4 @@ extern int fdatasync(int fildes); /* /port compatibility functions */ #include "port.h" -#endif /* C_H */ +#endif /* C_H */