diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/c.h | 195 | ||||
-rw-r--r-- | src/include/postgres.h | 54 | ||||
-rw-r--r-- | src/include/postgres_fe.h | 12 |
3 files changed, 136 insertions, 125 deletions
diff --git a/src/include/c.h b/src/include/c.h index 230229c80e4..7c5ac8642ac 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -31,9 +31,10 @@ * 3) standard system types * 4) IsValid macros for system types * 5) offsetof, lengthof, endof, alignment - * 6) widely useful macros - * 7) random stuff - * 8) system-specific hacks + * 6) assertions + * 7) widely useful macros + * 8) random stuff + * 9) system-specific hacks * * NOTE: since this file is included by both frontend and backend modules, it's * almost certainly wrong to put an "extern" declaration here. typedefs and @@ -550,7 +551,134 @@ typedef NameData *Name; #define MAXALIGN_DOWN(LEN) TYPEALIGN_DOWN(MAXIMUM_ALIGNOF, (LEN)) /* ---------------------------------------------------------------- - * Section 6: widely useful macros + * Section 6: assertions + * ---------------------------------------------------------------- + */ + +/* + * USE_ASSERT_CHECKING, if defined, turns on all the assertions. + * - plai 9/5/90 + * + * It should _NOT_ be defined in releases or in benchmark copies + */ + +/* + * Assert() can be used in both frontend and backend code. In frontend code it + * just calls the standard assert, if it's available. If use of assertions is + * not configured, it does nothing. + */ +#ifndef USE_ASSERT_CHECKING + +#define Assert(condition) +#define AssertMacro(condition) ((void)true) +#define AssertArg(condition) +#define AssertState(condition) + +#elif defined(FRONTEND) + +#include <assert.h> +#define Assert(p) assert(p) +#define AssertMacro(p) ((void) assert(p)) +#define AssertArg(condition) assert(condition) +#define AssertState(condition) assert(condition) + +#else /* USE_ASSERT_CHECKING && FRONTEND */ + +/* + * Trap + * Generates an exception if the given condition is true. + */ +#define Trap(condition, errorType) \ + do { \ + if ((assert_enabled) && (condition)) \ + ExceptionalCondition(CppAsString(condition), (errorType), \ + __FILE__, __LINE__); \ + } while (0) + +/* + * TrapMacro is the same as Trap but it's intended for use in macros: + * + * #define foo(x) (AssertMacro(x != 0), bar(x)) + * + * Isn't CPP fun? + */ +#define TrapMacro(condition, errorType) \ + ((bool) ((! assert_enabled) || ! (condition) || \ + (ExceptionalCondition(CppAsString(condition), (errorType), \ + __FILE__, __LINE__), 0))) + +#define Assert(condition) \ + Trap(!(condition), "FailedAssertion") + +#define AssertMacro(condition) \ + ((void) TrapMacro(!(condition), "FailedAssertion")) + +#define AssertArg(condition) \ + Trap(!(condition), "BadArgument") + +#define AssertState(condition) \ + Trap(!(condition), "BadState") + +#endif /* USE_ASSERT_CHECKING && !FRONTEND */ + + +/* + * Macros to support compile-time assertion checks. + * + * If the "condition" (a compile-time-constant expression) evaluates to false, + * throw a compile error using the "errmessage" (a string literal). + * + * gcc 4.6 and up supports _Static_assert(), but there are bizarre syntactic + * placement restrictions. These macros make it safe to use as a statement + * or in an expression, respectively. + * + * Otherwise we fall back on a kluge that assumes the compiler will complain + * about a negative width for a struct bit-field. This will not include a + * helpful error message, but it beats not getting an error at all. + */ +#ifdef HAVE__STATIC_ASSERT +#define StaticAssertStmt(condition, errmessage) \ + do { _Static_assert(condition, errmessage); } while(0) +#define StaticAssertExpr(condition, errmessage) \ + ({ StaticAssertStmt(condition, errmessage); true; }) +#else /* !HAVE__STATIC_ASSERT */ +#define StaticAssertStmt(condition, errmessage) \ + ((void) sizeof(struct { int static_assert_failure : (condition) ? 1 : -1; })) +#define StaticAssertExpr(condition, errmessage) \ + StaticAssertStmt(condition, errmessage) +#endif /* HAVE__STATIC_ASSERT */ + + +/* + * Compile-time checks that a variable (or expression) has the specified type. + * + * AssertVariableIsOfType() can be used as a statement. + * AssertVariableIsOfTypeMacro() is intended for use in macros, eg + * #define foo(x) (AssertVariableIsOfTypeMacro(x, int), bar(x)) + * + * If we don't have __builtin_types_compatible_p, we can still assert that + * the types have the same size. This is far from ideal (especially on 32-bit + * platforms) but it provides at least some coverage. + */ +#ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P +#define AssertVariableIsOfType(varname, typename) \ + StaticAssertStmt(__builtin_types_compatible_p(__typeof__(varname), typename), \ + CppAsString(varname) " does not have type " CppAsString(typename)) +#define AssertVariableIsOfTypeMacro(varname, typename) \ + ((void) StaticAssertExpr(__builtin_types_compatible_p(__typeof__(varname), typename), \ + CppAsString(varname) " does not have type " CppAsString(typename))) +#else /* !HAVE__BUILTIN_TYPES_COMPATIBLE_P */ +#define AssertVariableIsOfType(varname, typename) \ + StaticAssertStmt(sizeof(varname) == sizeof(typename), \ + CppAsString(varname) " does not have type " CppAsString(typename)) +#define AssertVariableIsOfTypeMacro(varname, typename) \ + ((void) StaticAssertExpr(sizeof(varname) == sizeof(typename), \ + CppAsString(varname) " does not have type " CppAsString(typename))) +#endif /* HAVE__BUILTIN_TYPES_COMPATIBLE_P */ + + +/* ---------------------------------------------------------------- + * Section 7: widely useful macros * ---------------------------------------------------------------- */ /* @@ -694,61 +822,6 @@ typedef NameData *Name; /* - * Macros to support compile-time assertion checks. - * - * If the "condition" (a compile-time-constant expression) evaluates to false, - * throw a compile error using the "errmessage" (a string literal). - * - * gcc 4.6 and up supports _Static_assert(), but there are bizarre syntactic - * placement restrictions. These macros make it safe to use as a statement - * or in an expression, respectively. - * - * Otherwise we fall back on a kluge that assumes the compiler will complain - * about a negative width for a struct bit-field. This will not include a - * helpful error message, but it beats not getting an error at all. - */ -#ifdef HAVE__STATIC_ASSERT -#define StaticAssertStmt(condition, errmessage) \ - do { _Static_assert(condition, errmessage); } while(0) -#define StaticAssertExpr(condition, errmessage) \ - ({ StaticAssertStmt(condition, errmessage); true; }) -#else /* !HAVE__STATIC_ASSERT */ -#define StaticAssertStmt(condition, errmessage) \ - ((void) sizeof(struct { int static_assert_failure : (condition) ? 1 : -1; })) -#define StaticAssertExpr(condition, errmessage) \ - StaticAssertStmt(condition, errmessage) -#endif /* HAVE__STATIC_ASSERT */ - - -/* - * Compile-time checks that a variable (or expression) has the specified type. - * - * AssertVariableIsOfType() can be used as a statement. - * AssertVariableIsOfTypeMacro() is intended for use in macros, eg - * #define foo(x) (AssertVariableIsOfTypeMacro(x, int), bar(x)) - * - * If we don't have __builtin_types_compatible_p, we can still assert that - * the types have the same size. This is far from ideal (especially on 32-bit - * platforms) but it provides at least some coverage. - */ -#ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P -#define AssertVariableIsOfType(varname, typename) \ - StaticAssertStmt(__builtin_types_compatible_p(__typeof__(varname), typename), \ - CppAsString(varname) " does not have type " CppAsString(typename)) -#define AssertVariableIsOfTypeMacro(varname, typename) \ - ((void) StaticAssertExpr(__builtin_types_compatible_p(__typeof__(varname), typename), \ - CppAsString(varname) " does not have type " CppAsString(typename))) -#else /* !HAVE__BUILTIN_TYPES_COMPATIBLE_P */ -#define AssertVariableIsOfType(varname, typename) \ - StaticAssertStmt(sizeof(varname) == sizeof(typename), \ - CppAsString(varname) " does not have type " CppAsString(typename)) -#define AssertVariableIsOfTypeMacro(varname, typename) \ - ((void) StaticAssertExpr(sizeof(varname) == sizeof(typename), \ - CppAsString(varname) " does not have type " CppAsString(typename))) -#endif /* HAVE__BUILTIN_TYPES_COMPATIBLE_P */ - - -/* * Mark a point as unreachable in a portable fashion. This should preferably * be something that the compiler understands, to aid code generation. * In assert-enabled builds, we prefer abort() for debugging reasons. @@ -781,7 +854,7 @@ typedef NameData *Name; #endif /* PG_USE_INLINE */ /* ---------------------------------------------------------------- - * Section 7: random stuff + * Section 8: random stuff * ---------------------------------------------------------------- */ @@ -835,7 +908,7 @@ typedef NameData *Name; /* ---------------------------------------------------------------- - * Section 8: system-specific hacks + * Section 9: system-specific hacks * * This should be limited to things that absolutely have to be * included in every source file. The port-specific header file diff --git a/src/include/postgres.h b/src/include/postgres.h index 8ff107a7b3f..207f7b8ffb2 100644 --- a/src/include/postgres.h +++ b/src/include/postgres.h @@ -25,7 +25,7 @@ * ------- ------------------------------------------------ * 1) variable-length datatypes (TOAST support) * 2) datum type + support macros - * 3) exception handling definitions + * 3) exception handling backend support * * NOTES * @@ -634,62 +634,12 @@ extern Datum Float8GetDatum(float8 X); /* ---------------------------------------------------------------- - * Section 3: exception handling definitions - * Assert, Trap, etc macros + * Section 3: exception handling backend support * ---------------------------------------------------------------- */ extern PGDLLIMPORT bool assert_enabled; -/* - * USE_ASSERT_CHECKING, if defined, turns on all the assertions. - * - plai 9/5/90 - * - * It should _NOT_ be defined in releases or in benchmark copies - */ - -/* - * Trap - * Generates an exception if the given condition is true. - */ -#define Trap(condition, errorType) \ - do { \ - if ((assert_enabled) && (condition)) \ - ExceptionalCondition(CppAsString(condition), (errorType), \ - __FILE__, __LINE__); \ - } while (0) - -/* - * TrapMacro is the same as Trap but it's intended for use in macros: - * - * #define foo(x) (AssertMacro(x != 0), bar(x)) - * - * Isn't CPP fun? - */ -#define TrapMacro(condition, errorType) \ - ((bool) ((! assert_enabled) || ! (condition) || \ - (ExceptionalCondition(CppAsString(condition), (errorType), \ - __FILE__, __LINE__), 0))) - -#ifndef USE_ASSERT_CHECKING -#define Assert(condition) -#define AssertMacro(condition) ((void)true) -#define AssertArg(condition) -#define AssertState(condition) -#else -#define Assert(condition) \ - Trap(!(condition), "FailedAssertion") - -#define AssertMacro(condition) \ - ((void) TrapMacro(!(condition), "FailedAssertion")) - -#define AssertArg(condition) \ - Trap(!(condition), "BadArgument") - -#define AssertState(condition) \ - Trap(!(condition), "BadState") -#endif /* USE_ASSERT_CHECKING */ - extern void ExceptionalCondition(const char *conditionName, const char *errorType, const char *fileName, int lineNumber) __attribute__((noreturn)); diff --git a/src/include/postgres_fe.h b/src/include/postgres_fe.h index af31227b0ba..0f35eccc748 100644 --- a/src/include/postgres_fe.h +++ b/src/include/postgres_fe.h @@ -24,16 +24,4 @@ #include "c.h" -/* - * Assert() can be used in both frontend and backend code. In frontend code it - * just calls the standard assert, if it's available. If use of assertions is - * not configured, it does nothing. - */ -#ifdef USE_ASSERT_CHECKING -#include <assert.h> -#define Assert(p) assert(p) -#else -#define Assert(p) -#endif - #endif /* POSTGRES_FE_H */ |