Skip to content

Commit 8fef0c3

Browse files
committed
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-
1 parent f90860f commit 8fef0c3

File tree

2 files changed

+23
-1
lines changed

2 files changed

+23
-1
lines changed

src/backend/tcop/postgres.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -855,7 +855,7 @@ pg_plan_queries(List *querytrees, int cursorOptions, ParamListInfo boundParams)
855855

856856
foreach(query_list, querytrees)
857857
{
858-
Query *query = (Query *) lfirst(query_list);
858+
Query *query = castNode(Query, lfirst(query_list));
859859
Node *stmt;
860860

861861
if (query->commandType == CMD_UTILITY)

src/include/nodes/nodes.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,28 @@ extern PGDLLIMPORT Node *newNodeMacroHolder;
512512

513513
#define IsA(nodeptr,_type_) (nodeTag(nodeptr) == T_##_type_)
514514

515+
/*
516+
* castNode(type, ptr) casts ptr to type and, if cassert is enabled, verifies
517+
* that the the c actually has the appropriate type (using it's nodeTag()).
518+
*
519+
* Use an inline function when assertions are enabled, to avoid multiple
520+
* evaluations of the ptr argument (which could e.g. be a function call). If
521+
* inline functions are not available - only a small number of platforms -
522+
* don't Assert, but use the non-checking version.
523+
*/
524+
#if defined(USE_ASSERT_CHECKING) && defined(PG_USE_INLINE)
525+
static inline Node*
526+
castNodeImpl(enum NodeTag type, void *ptr)
527+
{
528+
Assert(ptr == NULL || nodeTag(ptr) == type);
529+
return ptr;
530+
}
531+
#define castNode(_type_, nodeptr) ((_type_ *) castNodeImpl(T_##_type_, nodeptr))
532+
#else
533+
#define castNode(_type_,nodeptr) ((_type_ *)(nodeptr))
534+
#endif
535+
536+
515537
/* ----------------------------------------------------------------
516538
* extern declarations follow
517539
* ----------------------------------------------------------------

0 commit comments

Comments
 (0)