Commit e1d25de3 authored by Alvaro Herrera's avatar Alvaro Herrera

Move Assert() definitions to c.h

This way, they can be used by frontend and backend code.  We already
supported that, but doing it this way allows us to mix true frontend
files with backend files compiled in frontend environment.

Author: Andres Freund
parent dd1569da
......@@ -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
* ----------------------------------------------------------------
*/
/*
......@@ -693,61 +821,6 @@ typedef NameData *Name;
} while (0)
/*
* 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.
......@@ -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
......
......@@ -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));
......
......@@ -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 */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment