postgres.git / summary / log / commit / refs

commit    8fef0c34143ba45d4efcd0c352dee23602be54af
Author:   Andres Freund <andres@anarazel.de>
Date:     Fri Jan 27 00:47:03 2017 +0000

    Add castNode(type, ptr) for safe casting between NodeTag based types.
    
    The new function allows to cast from one NodeTag based type to
    another, while asserting that the conversion is valid.  This replaces
    the common pattern of doing a cast and a Assert(IsA(ptr, type))
    close-by.
    
    As this seems likely to be used pervasively, we decided to backpatch
    this change the addition of this macro. Otherwise backpatched fixes
    are more likely not to work on back-branches.
    
    On branches before 9.6, where we do not yet rely on inline functions
    being available, the type assertion is only performed if PG_USE_INLINE
    support is detected. The cast obviously is performed regardless.
    
    For the benefit of verifying the macro compiles in the back-branches,
    this commit contains a single use of the new macro. On master, a
    somewhat larger conversion will be committed separately.
    
    Author: Peter Eisentraut and Andres Freund
    Reviewed-By: Tom Lane
    Discussion: https://postgr.es/m/c5d387d9-3440-f5e0-f9d4-71d53b9fbe52@2ndquadrant.com
    Backpatch: 9.2-


src/backend/tcop/postgres.c | 2 +- src/include/nodes/nodes.h | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index fce16fe6cb1..242ca4445df 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -855,7 +855,7 @@ pg_plan_queries(List *querytrees, int cursorOptions, ParamListInfo boundParams) foreach(query_list, querytrees) { - Query *query = (Query *) lfirst(query_list); + Query *query = castNode(Query, lfirst(query_list)); Node *stmt; if (query->commandType == CMD_UTILITY) diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index 91505c81d9c..8ed3572bdb9 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -512,6 +512,28 @@ extern PGDLLIMPORT Node *newNodeMacroHolder; #define IsA(nodeptr,_type_) (nodeTag(nodeptr) == T_##_type_) +/* + * castNode(type, ptr) casts ptr to type and, if cassert is enabled, verifies + * that the the c actually has the appropriate type (using it's nodeTag()). + * + * Use an inline function when assertions are enabled, to avoid multiple + * evaluations of the ptr argument (which could e.g. be a function call). If + * inline functions are not available - only a small number of platforms - + * don't Assert, but use the non-checking version. + */ +#if defined(USE_ASSERT_CHECKING) && defined(PG_USE_INLINE) +static inline Node* +castNodeImpl(enum NodeTag type, void *ptr) +{ + Assert(ptr == NULL || nodeTag(ptr) == type); + return ptr; +} +#define castNode(_type_, nodeptr) ((_type_ *) castNodeImpl(T_##_type_, nodeptr)) +#else +#define castNode(_type_,nodeptr) ((_type_ *)(nodeptr)) +#endif + + /* ---------------------------------------------------------------- * extern declarations follow * ---------------------------------------------------------------- [parent: f90860f339f6]