Skip to content

Commit

Permalink
Add castNode(type, ptr) for safe casting between NodeTag based types.
Browse files Browse the repository at this point in the history
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/[email protected]
Backpatch: 9.2-
  • Loading branch information
anarazel committed Jan 27, 2017
1 parent 331f8c3 commit 5bcab11
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/backend/tcop/postgres.c
Original file line number Diff line number Diff line change
Expand Up @@ -846,7 +846,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));
PlannedStmt *stmt;

if (query->commandType == CMD_UTILITY)
Expand Down
20 changes: 20 additions & 0 deletions src/include/nodes/nodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,26 @@ 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).
*/
#ifdef USE_ASSERT_CHECKING
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
* ----------------------------------------------------------------
Expand Down

0 comments on commit 5bcab11

Please sign in to comment.