Subject: Re: Tree-walker callbacks vs -Wdeprecated-non-prototype

From: Tom Lane <[email-masked]>
Date: Sun, 01 May 2022 20:02:45 -0400

Thomas Munro <[email-masked]> writes:
> As visible on seawasp (and noticed here in passing, while hacking on
> the opaque pointer changes for bleeding edge LLVM), Clang 15 now warns
> by default about our use of tree walkers functions with no function
> prototype, because the next revision of C (C23?) will apparently be
> harmonising with C++ in interpreting f() to mean f(void), not
> f(anything goes).

Ugh.  I wonder if we can get away with declaring the walker arguments
as something like "bool (*walker) (Node *, void *)" without having
to change all the actual walkers to be exactly that signature.
Having to insert casts in the walkers would be a major pain-in-the-butt.

			regards, tom lane

---

From: Tom Lane <[email-masked]>
Date: Fri, 16 Sep 2022 21:08:02 -0400

> Having to insert casts in the walkers would be a major pain-in-the-butt.

No joy on that: both gcc and clang want the walkers to be declared
as taking exactly "void *".

Attached is an incomplete POC patch that suppresses these warnings
in nodeFuncs.c itself and in costsize.c, which I selected at random
as a typical caller.  I'll push forward with converting the other
call sites if this way seems good to people.

In nodeFuncs.c, we can hide the newly-required casts inside macros;
indeed, the mutators barely need any changes because they already
had MUTATE() macros that contained casts.  So on that side, it feels
to me that this is actually a bit nicer than before.

For the callers, we can either do it as I did below:

 static bool
-cost_qual_eval_walker(Node *node, cost_qual_eval_context *context)
+cost_qual_eval_walker(Node *node, void *ctx)
 {
+	cost_qual_eval_context *context = (cost_qual_eval_context *) ctx;
+
 	if (node == NULL)
 		return false;

or perhaps like this:

 static bool
-cost_qual_eval_walker(Node *node, cost_qual_eval_context *context)
+cost_qual_eval_walker(Node *node, void *context)
 {
+	cost_qual_eval_context *cqctx = (cost_qual_eval_context *) context;
+
 	if (node == NULL)
 		return false;

but the latter would require changing references further down in the
function, so I felt it more invasive.

It's sad to note that this exercise in hoop-jumping actually leaves
us with net LESS type safety, because the outside callers of
cost_qual_eval_walker are no longer constrained to call it with
the appropriate kind of context struct.  Thanks, C committee.

			regards, tom lane

diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c
index 3bac350bf5..1e2ae3a5a4 100644
--- a/src/backend/nodes/nodeFuncs.c
+++ b/src/backend/nodes/nodeFuncs.c
@@ -27,10 +27,10 @@
 static bool expression_returns_set_walker(Node *node, void *context);
 static int	leftmostLoc(int loc1, int loc2);
 static bool fix_opfuncids_walker(Node *node, void *context);
-static bool planstate_walk_subplans(List *plans, bool (*walker) (),
+static bool planstate_walk_subplans(List *plans, tree_walker_callback walker,
 									void *context);
 static bool planstate_walk_members(PlanState **planstates, int nplans,
-								   bool (*walker) (), void *context);
+								   tree_walker_callback walker, void *context);

 /*
@@ -1836,7 +1836,7 @@ check_functions_in_node(Node *node, check_function_callback checker,
  * that modify nodes in-place but never add/delete/replace nodes).
  * A walker routine should look like this:
  *
- * bool my_walker (Node *node, my_struct *context)
+ * bool my_walker (Node *node, void *context)
  * {
  *		if (node == NULL)
  *			return false;
@@ -1850,7 +1850,7 @@ check_functions_in_node(Node *node, check_function_callback checker,
  *			... do special actions for other node types
  *		}
  *		// for any node type not specially processed, do:
- *		return expression_tree_walker(node, my_walker, (void *) context);
+ *		return expression_tree_walker(node, my_walker, context);
  * }
  *
  * The "context" argument points to a struct that holds whatever context
@@ -1910,7 +1910,7 @@ check_functions_in_node(Node *node, check_function_callback checker,
 
 bool
 expression_tree_walker(Node *node,
-					   bool (*walker) (),
+					   tree_walker_callback walker,
 					   void *context)
 {
 	ListCell   *temp;
@@ -1923,6 +1923,10 @@ expression_tree_walker(Node *node,
 	 * when we expect a List we just recurse directly to self without
 	 * bothering to call the walker.
 	 */
+#define WALK(n) walker((Node *) (n), context)
+
+#define LIST_WALK(l) expression_tree_walker((Node *) (l), walker, context)
+
 	if (node == NULL)
 		return false;
 
@@ -1946,25 +1950,21 @@ expression_tree_walker(Node *node,
 			/* primitive node types with no expression subnodes */
 			break;
 		case T_WithCheckOption:
-			return walker(((WithCheckOption *) node)->qual, context);
+			return WALK(((WithCheckOption *) node)->qual);
 		case T_Aggref:
 			{
 				Aggref	   *expr = (Aggref *) node;
 
-				/* recurse directly on List */
-				if (expression_tree_walker((Node *) expr->aggdirectargs,
-										   walker, context))
+				/* recurse directly on Lists */
+				if (LIST_WALK(expr->aggdirectargs))
 					return true;
-				if (expression_tree_walker((Node *) expr->args,
-										   walker, context))
+				if (LIST_WALK(expr->args))
 					return true;
-				if (expression_tree_walker((Node *) expr->aggorder,
-										   walker, context))
+				if (LIST_WALK(expr->aggorder))
 					return true;
-				if (expression_tree_walker((Node *) expr->aggdistinct,
-										   walker, context))
+				if (LIST_WALK(expr->aggdistinct))
 					return true;
-				if (walker((Node *) expr->aggfilter, context))
+				if (WALK(expr->aggfilter))
 					return true;
 			}
 			break;
@@ -1972,8 +1972,7 @@ expression_tree_walker(Node *node,
 			{
 				GroupingFunc *grouping = (GroupingFunc *) node;
 
-				if (expression_tree_walker((Node *) grouping->args,
-										   walker, context))
+				if (LIST_WALK(grouping->args))
 					return true;
 			}
 			break;
@@ -1982,10 +1981,9 @@ expression_tree_walker(Node *node,
 				WindowFunc *expr = (WindowFunc *) node;
 
 				/* recurse directly on List */
-				if (expression_tree_walker((Node *) expr->args,
-										   walker, context))
+				if (LIST_WALK(expr->args))
 					return true;
-				if (walker((Node *) expr->aggfilter, context))
+				if (WALK(expr->aggfilter))
 					return true;
 			}
 			break;
@@ -1994,17 +1992,15 @@ expression_tree_walker(Node *node,
 				SubscriptingRef *sbsref = (SubscriptingRef *) node;
 
 				/* recurse directly for upper/lower container index lists */
-				if (expression_tree_walker((Node *) sbsref->refupperindexpr,
-										   walker, context))
+				if (LIST_WALK(sbsref->refupperindexpr))
 					return true;
-				if (expression_tree_walker((Node *) sbsref->reflowerindexpr,
-										   walker, context))
+				if (LIST_WALK(sbsref->reflowerindexpr))
 					return true;
 				/* walker must see the refexpr and refassgnexpr, however */
-				if (walker(sbsref->refexpr, context))
+				if (WALK(sbsref->refexpr))
 					return true;
 
-				if (walker(sbsref->refassgnexpr, context))
+				if (WALK(sbsref->refassgnexpr))
 					return true;
 			}
 			break;
@@ -2012,21 +2008,19 @@ expression_tree_walker(Node *node,
 			{
 				FuncExpr   *expr = (FuncExpr *) node;
 
-				if (expression_tree_walker((Node *) expr->args,
-										   walker, context))
+				if (LIST_WALK(expr->args))
 					return true;
 			}
 			break;
 		case T_NamedArgExpr:
-			return walker(((NamedArgExpr *) node)->arg, context);
+			return WALK(((NamedArgExpr *) node)->arg);
 		case T_OpExpr:
 		case T_DistinctExpr:	/* struct-equivalent to OpExpr */
 		case T_NullIfExpr:		/* struct-equivalent to OpExpr */
 			{
 				OpExpr	   *expr = (OpExpr *) node;
 
-				if (expression_tree_walker((Node *) expr->args,
-										   walker, context))
+				if (LIST_WALK(expr->args))
 					return true;
 			}
 			break;
@@ -2034,8 +2028,7 @@ expression_tree_walker(Node *node,
 			{
 				ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
 
-				if (expression_tree_walker((Node *) expr->args,
-										   walker, context))
+				if (LIST_WALK(expr->args))
 					return true;
 			}
 			break;
@@ -2043,8 +2036,7 @@ expression_tree_walker(Node *node,
 			{
 				BoolExpr   *expr = (BoolExpr *) node;
 
-				if (expression_tree_walker((Node *) expr->args,
-										   walker, context))
+				if (LIST_WALK(expr->args))
 					return true;
 			}
 			break;
@@ -2052,14 +2044,14 @@ expression_tree_walker(Node *node,
 			{
 				SubLink    *sublink = (SubLink *) node;
 
-				if (walker(sublink->testexpr, context))
+				if (WALK(sublink->testexpr))
 					return true;
 
 				/*
 				 * Also invoke the walker on the sublink's Query node, so it
 				 * can recurse into the sub-query if it wants to.
 				 */
-				return walker(sublink->subselect, context);
+				return WALK(sublink->subselect);
 			}
 			break;
 		case T_SubPlan:
@@ -2067,104 +2059,103 @@ expression_tree_walker(Node *node,
 				SubPlan    *subplan = (SubPlan *) node;
 
 				/* recurse into the testexpr, but not into the Plan */
-				if (walker(subplan->testexpr, context))
+				if (WALK(subplan->testexpr))
 					return true;
 				/* also examine args list */
-				if (expression_tree_walker((Node *) subplan->args,
-										   walker, context))
+				if (LIST_WALK(subplan->args))
 					return true;
 			}
 			break;
 		case T_AlternativeSubPlan:
-			return walker(((AlternativeSubPlan *) node)->subplans, context);
+			return LIST_WALK(((AlternativeSubPlan *) node)->subplans);
 		case T_FieldSelect:
-			return walker(((FieldSelect *) node)->arg, context);
+			return WALK(((FieldSelect *) node)->arg);
 		case T_FieldStore:
 			{
 				FieldStore *fstore = (FieldStore *) node;
 
-				if (walker(fstore->arg, context))
+				if (WALK(fstore->arg))
 					return true;
-				if (walker(fstore->newvals, context))
+				if (WALK(fstore->newvals))
 					return true;
 			}
 			break;
 		case T_RelabelType:
-			return walker(((RelabelType *) node)->arg, context);
+			return WALK(((RelabelType *) node)->arg);
 		case T_CoerceViaIO:
-			return walker(((CoerceViaIO *) node)->arg, context);
+			return WALK(((CoerceViaIO *) node)->arg);
 		case T_ArrayCoerceExpr:
 			{
 				ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
 
-				if (walker(acoerce->arg, context))
+				if (WALK(acoerce->arg))
 					return true;
-				if (walker(acoerce->elemexpr, context))
+				if (WALK(acoerce->elemexpr))
 					return true;
 			}
 			break;
 		case T_ConvertRowtypeExpr:
-			return walker(((ConvertRowtypeExpr *) node)->arg, context);
+			return WALK(((ConvertRowtypeExpr *) node)->arg);
 		case T_CollateExpr:
-			return walker(((CollateExpr *) node)->arg, context);
+			return WALK(((CollateExpr *) node)->arg);
 		case T_CaseExpr:
 			{
 				CaseExpr   *caseexpr = (CaseExpr *) node;
 
-				if (walker(caseexpr->arg, context))
+				if (WALK(caseexpr->arg))
 					return true;
 				/* we assume walker doesn't care about CaseWhens, either */
 				foreach(temp, caseexpr->args)
 				{
 					CaseWhen   *when = lfirst_node(CaseWhen, temp);
 
-					if (walker(when->expr, context))
+					if (WALK(when->expr))
 						return true;
-					if (walker(when->result, context))
+					if (WALK(when->result))
 						return true;
 				}
-				if (walker(caseexpr->defresult, context))
+				if (WALK(caseexpr->defresult))
 					return true;
 			}
 			break;
 		case T_ArrayExpr:
-			return walker(((ArrayExpr *) node)->elements, context);
+			return WALK(((ArrayExpr *) node)->elements);
 		case T_RowExpr:
 			/* Assume colnames isn't interesting */
-			return walker(((RowExpr *) node)->args, context);
+			return WALK(((RowExpr *) node)->args);
 		case T_RowCompareExpr:
 			{
 				RowCompareExpr *rcexpr = (RowCompareExpr *) node;
 
-				if (walker(rcexpr->largs, context))
+				if (WALK(rcexpr->largs))
 					return true;
-				if (walker(rcexpr->rargs, context))
+				if (WALK(rcexpr->rargs))
 					return true;
 			}
 			break;
 		case T_CoalesceExpr:
-			return walker(((CoalesceExpr *) node)->args, context);
+			return WALK(((CoalesceExpr *) node)->args);
 		case T_MinMaxExpr:
-			return walker(((MinMaxExpr *) node)->args, context);
+			return WALK(((MinMaxExpr *) node)->args);
 		case T_XmlExpr:
 			{
 				XmlExpr    *xexpr = (XmlExpr *) node;
 
-				if (walker(xexpr->named_args, context))
+				if (WALK(xexpr->named_args))
 					return true;
 				/* we assume walker doesn't care about arg_names */
-				if (walker(xexpr->args, context))
+				if (WALK(xexpr->args))
 					return true;
 			}
 			break;
 		case T_NullTest:
-			return walker(((NullTest *) node)->arg, context);
+			return WALK(((NullTest *) node)->arg);
 		case T_BooleanTest:
-			return walker(((BooleanTest *) node)->arg, context);
+			return WALK(((BooleanTest *) node)->arg);
 		case T_CoerceToDomain:
-			return walker(((CoerceToDomain *) node)->arg, context);
+			return WALK(((CoerceToDomain *) node)->arg);
 		case T_TargetEntry:
-			return walker(((TargetEntry *) node)->expr, context);
+			return WALK(((TargetEntry *) node)->expr);
 		case T_Query:
 			/* Do nothing with a sub-Query, per discussion above */
 			break;
@@ -2172,13 +2163,13 @@ expression_tree_walker(Node *node,
 			{
 				WindowClause *wc = (WindowClause *) node;
 
-				if (walker(wc->partitionClause, context))
+				if (WALK(wc->partitionClause))
 					return true;
-				if (walker(wc->orderClause, context))
+				if (WALK(wc->orderClause))
 					return true;
-				if (walker(wc->startOffset, context))
+				if (WALK(wc->startOffset))
 					return true;
-				if (walker(wc->endOffset, context))
+				if (WALK(wc->endOffset))
 					return true;
 			}
 			break;
@@ -2186,9 +2177,9 @@ expression_tree_walker(Node *node,
 			{
 				CTECycleClause *cc = (CTECycleClause *) node;
 
-				if (walker(cc->cycle_mark_value, context))
+				if (WALK(cc->cycle_mark_value))
 					return true;
-				if (walker(cc->cycle_mark_default, context))
+				if (WALK(cc->cycle_mark_default))
 					return true;
 			}
 			break;
@@ -2200,12 +2191,12 @@ expression_tree_walker(Node *node,
 				 * Invoke the walker on the CTE's Query node, so it can
 				 * recurse into the sub-query if it wants to.
 				 */
-				if (walker(cte->ctequery, context))
+				if (WALK(cte->ctequery))
 					return true;
 
-				if (walker(cte->search_clause, context))
+				if (WALK(cte->search_clause))
 					return true;
-				if (walker(cte->cycle_clause, context))
+				if (WALK(cte->cycle_clause))
 					return true;
 			}
 			break;
@@ -2213,11 +2204,11 @@ expression_tree_walker(Node *node,
 			{
 				PartitionBoundSpec *pbs = (PartitionBoundSpec *) node;
 
-				if (walker(pbs->listdatums, context))
+				if (WALK(pbs->listdatums))
 					return true;
-				if (walker(pbs->lowerdatums, context))
+				if (WALK(pbs->lowerdatums))
 					return true;
-				if (walker(pbs->upperdatums, context))
+				if (WALK(pbs->upperdatums))
 					return true;
 			}
 			break;
@@ -2225,14 +2216,14 @@ expression_tree_walker(Node *node,
 			{
 				PartitionRangeDatum *prd = (PartitionRangeDatum *) node;
 
-				if (walker(prd->value, context))
+				if (WALK(prd->value))
 					return true;
 			}
 			break;
 		case T_List:
 			foreach(temp, (List *) node)
 			{
-				if (walker((Node *) lfirst(temp), context))
+				if (WALK(lfirst(temp)))
 					return true;
 			}
 			break;
@@ -2240,9 +2231,9 @@ expression_tree_walker(Node *node,
 			{
 				FromExpr   *from = (FromExpr *) node;
 
-				if (walker(from->fromlist, context))
+				if (LIST_WALK(from->fromlist))
 					return true;
-				if (walker(from->quals, context))
+				if (WALK(from->quals))
 					return true;
 			}
 			break;
@@ -2250,15 +2241,15 @@ expression_tree_walker(Node *node,
 			{
 				OnConflictExpr *onconflict = (OnConflictExpr *) node;
 
-				if (walker((Node *) onconflict->arbiterElems, context))
+				if (WALK(onconflict->arbiterElems))
 					return true;
-				if (walker(onconflict->arbiterWhere, context))
+				if (WALK(onconflict->arbiterWhere))
 					return true;
-				if (walker(onconflict->onConflictSet, context))
+				if (WALK(onconflict->onConflictSet))
 					return true;
-				if (walker(onconflict->onConflictWhere, context))
+				if (WALK(onconflict->onConflictWhere))
 					return true;
-				if (walker(onconflict->exclRelTlist, context))
+				if (WALK(onconflict->exclRelTlist))
 					return true;
 			}
 			break;
@@ -2266,9 +2257,9 @@ expression_tree_walker(Node *node,
 			{
 				MergeAction *action = (MergeAction *) node;
 
-				if (walker(action->targetList, context))
+				if (WALK(action->targetList))
 					return true;
-				if (walker(action->qual, context))
+				if (WALK(action->qual))
 					return true;
 			}
 			break;
@@ -2276,7 +2267,7 @@ expression_tree_walker(Node *node,
 			{
 				PartitionPruneStepOp *opstep = (PartitionPruneStepOp *) node;
 
-				if (walker((Node *) opstep->exprs, context))
+				if (WALK(opstep->exprs))
 					return true;
 			}
 			break;
@@ -2287,11 +2278,11 @@ expression_tree_walker(Node *node,
 			{
 				JoinExpr   *join = (JoinExpr *) node;
 
-				if (walker(join->larg, context))
+				if (WALK(join->larg))
 					return true;
-				if (walker(join->rarg, context))
+				if (WALK(join->rarg))
 					return true;
-				if (walker(join->quals, context))
+				if (WALK(join->quals))
 					return true;
 
 				/*
@@ -2303,9 +2294,9 @@ expression_tree_walker(Node *node,
 			{
 				SetOperationStmt *setop = (SetOperationStmt *) node;
 
-				if (walker(setop->larg, context))
+				if (WALK(setop->larg))
 					return true;
-				if (walker(setop->rarg, context))
+				if (WALK(setop->rarg))
 					return true;
 
 				/* groupClauses are deemed uninteresting */
@@ -2315,38 +2306,35 @@ expression_tree_walker(Node *node,
 			{
 				IndexClause *iclause = (IndexClause *) node;
 
-				if (walker(iclause->rinfo, context))
+				if (WALK(iclause->rinfo))
 					return true;
-				if (expression_tree_walker((Node *) iclause->indexquals,
-										   walker, context))
+				if (LIST_WALK(iclause->indexquals))
 					return true;
 			}
 			break;
 		case T_PlaceHolderVar:
-			return walker(((PlaceHolderVar *) node)->phexpr, context);
+			return WALK(((PlaceHolderVar *) node)->phexpr);
 		case T_InferenceElem:
-			return walker(((InferenceElem *) node)->expr, context);
+			return WALK(((InferenceElem *) node)->expr);
 		case T_AppendRelInfo:
 			{
 				AppendRelInfo *appinfo = (AppendRelInfo *) node;
 
-				if (expression_tree_walker((Node *) appinfo->translated_vars,
-										   walker, context))
+				if (LIST_WALK(appinfo->translated_vars))
 					return true;
 			}
 			break;
 		case T_PlaceHolderInfo:
-			return walker(((PlaceHolderInfo *) node)->ph_var, context);
+			return WALK(((PlaceHolderInfo *) node)->ph_var);
 		case T_RangeTblFunction:
-			return walker(((RangeTblFunction *) node)->funcexpr, context);
+			return WALK(((RangeTblFunction *) node)->funcexpr);
 		case T_TableSampleClause:
 			{
 				TableSampleClause *tsc = (TableSampleClause *) node;
 
-				if (expression_tree_walker((Node *) tsc->args,
-										   walker, context))
+				if (LIST_WALK(tsc->args))
 					return true;
-				if (walker((Node *) tsc->repeatable, context))
+				if (WALK(tsc->repeatable))
 					return true;
 			}
 			break;
@@ -2354,15 +2342,15 @@ expression_tree_walker(Node *node,
 			{
 				TableFunc  *tf = (TableFunc *) node;
 
-				if (walker(tf->ns_uris, context))
+				if (WALK(tf->ns_uris))
 					return true;
-				if (walker(tf->docexpr, context))
+				if (WALK(tf->docexpr))
 					return true;
-				if (walker(tf->rowexpr, context))
+				if (WALK(tf->rowexpr))
 					return true;
-				if (walker(tf->colexprs, context))
+				if (WALK(tf->colexprs))
 					return true;
-				if (walker(tf->coldefexprs, context))
+				if (WALK(tf->coldefexprs))
 					return true;
 			}
 			break;
@@ -2372,6 +2360,9 @@ expression_tree_walker(Node *node,
 			break;
 	}
 	return false;
+
+	/* The WALK() macro can be re-used below, but LIST_WALK() not so much */
+#undef LIST_WALK
 }
 
 /*
@@ -2391,7 +2382,7 @@ expression_tree_walker(Node *node,
  */
 bool
 query_tree_walker(Query *query,
-				  bool (*walker) (),
+				  tree_walker_callback walker,
 				  void *context,
 				  int flags)
 {
@@ -2404,25 +2395,25 @@ query_tree_walker(Query *query,
 	 * in a rule action.
 	 */
 
-	if (walker((Node *) query->targetList, context))
+	if (WALK(query->targetList))
 		return true;
-	if (walker((Node *) query->withCheckOptions, context))
+	if (WALK(query->withCheckOptions))
 		return true;
-	if (walker((Node *) query->onConflict, context))
+	if (WALK(query->onConflict))
 		return true;
-	if (walker((Node *) query->mergeActionList, context))
+	if (WALK(query->mergeActionList))
 		return true;
-	if (walker((Node *) query->returningList, context))
+	if (WALK(query->returningList))
 		return true;
-	if (walker((Node *) query->jointree, context))
+	if (WALK(query->jointree))
 		return true;
-	if (walker(query->setOperations, context))
+	if (WALK(query->setOperations))
 		return true;
-	if (walker(query->havingQual, context))
+	if (WALK(query->havingQual))
 		return true;
-	if (walker(query->limitOffset, context))
+	if (WALK(query->limitOffset))
 		return true;
-	if (walker(query->limitCount, context))
+	if (WALK(query->limitCount))
 		return true;
 
 	/*
@@ -2432,13 +2423,13 @@ query_tree_walker(Query *query,
 	 */
 	if ((flags & QTW_EXAMINE_SORTGROUP))
 	{
-		if (walker((Node *) query->groupClause, context))
+		if (WALK(query->groupClause))
 			return true;
-		if (walker((Node *) query->windowClause, context))
+		if (WALK(query->windowClause))
 			return true;
-		if (walker((Node *) query->sortClause, context))
+		if (WALK(query->sortClause))
 			return true;
-		if (walker((Node *) query->distinctClause, context))
+		if (WALK(query->distinctClause))
 			return true;
 	}
 	else
@@ -2453,9 +2444,9 @@ query_tree_walker(Query *query,
 		{
 			WindowClause *wc = lfirst_node(WindowClause, lc);
 
-			if (walker(wc->startOffset, context))
+			if (WALK(wc->startOffset))
 				return true;
-			if (walker(wc->endOffset, context))
+			if (WALK(wc->endOffset))
 				return true;
 		}
 	}
@@ -2474,7 +2465,7 @@ query_tree_walker(Query *query,
 
 	if (!(flags & QTW_IGNORE_CTE_SUBQUERIES))
 	{
-		if (walker((Node *) query->cteList, context))
+		if (WALK(query->cteList))
 			return true;
 	}
 	if (!(flags & QTW_IGNORE_RANGE_TABLE))
@@ -2492,7 +2483,7 @@ query_tree_walker(Query *query,
  */
 bool
 range_table_walker(List *rtable,
-				   bool (*walker) (),
+				   tree_walker_callback walker,
 				   void *context,
 				   int flags)
 {
@@ -2513,7 +2504,7 @@ range_table_walker(List *rtable,
  */
 bool
 range_table_entry_walker(RangeTblEntry *rte,
-						 bool (*walker) (),
+						 tree_walker_callback walker,
 						 void *context,
 						 int flags)
 {
@@ -2523,35 +2514,35 @@ range_table_entry_walker(RangeTblEntry *rte,
 	 * specify neither flag, the walker won't be called on the RTE at all.
 	 */
 	if (flags & QTW_EXAMINE_RTES_BEFORE)
-		if (walker(rte, context))
+		if (WALK(rte))
 			return true;
 
 	switch (rte->rtekind)
 	{
 		case RTE_RELATION:
-			if (walker(rte->tablesample, context))
+			if (WALK(rte->tablesample))
 				return true;
 			break;
 		case RTE_SUBQUERY:
 			if (!(flags & QTW_IGNORE_RT_SUBQUERIES))
-				if (walker(rte->subquery, context))
+				if (WALK(rte->subquery))
 					return true;
 			break;
 		case RTE_JOIN:
 			if (!(flags & QTW_IGNORE_JOINALIASES))
-				if (walker(rte->joinaliasvars, context))
+				if (WALK(rte->joinaliasvars))
 					return true;
 			break;
 		case RTE_FUNCTION:
-			if (walker(rte->functions, context))
+			if (WALK(rte->functions))
 				return true;
 			break;
 		case RTE_TABLEFUNC:
-			if (walker(rte->tablefunc, context))
+			if (WALK(rte->tablefunc))
 				return true;
 			break;
 		case RTE_VALUES:
-			if (walker(rte->values_lists, context))
+			if (WALK(rte->values_lists))
 				return true;
 			break;
 		case RTE_CTE:
@@ -2561,11 +2552,11 @@ range_table_entry_walker(RangeTblEntry *rte,
 			break;
 	}
 
-	if (walker(rte->securityQuals, context))
+	if (WALK(rte->securityQuals))
 		return true;
 
 	if (flags & QTW_EXAMINE_RTES_AFTER)
-		if (walker(rte, context))
+		if (WALK(rte))
 			return true;
 
 	return false;
@@ -2580,7 +2571,7 @@ range_table_entry_walker(RangeTblEntry *rte,
  * (or appropriately modified substitute for) the subtree it is handed.
  * A mutator routine should look like this:
  *
- * Node * my_mutator (Node *node, my_struct *context)
+ * Node * my_mutator (Node *node, void *context)
  * {
  *		if (node == NULL)
  *			return NULL;
@@ -2594,7 +2585,7 @@ range_table_entry_walker(RangeTblEntry *rte,
  *			... do special transformations of other node types
  *		}
  *		// for any node type not specially processed, do:
- *		return expression_tree_mutator(node, my_mutator, (void *) context);
+ *		return expression_tree_mutator(node, my_mutator, context);
  * }
  *
  * The "context" argument points to a struct that holds whatever context
@@ -2636,7 +2627,7 @@ range_table_entry_walker(RangeTblEntry *rte,
 
 Node *
 expression_tree_mutator(Node *node,
-						Node *(*mutator) (),
+						tree_mutator_callback mutator,
 						void *context)
 {
 	/*
@@ -3367,7 +3358,7 @@ expression_tree_mutator(Node *node,
  */
 Query *
 query_tree_mutator(Query *query,
-				   Node *(*mutator) (),
+				   tree_mutator_callback mutator,
 				   void *context,
 				   int flags)
 {
@@ -3457,7 +3448,7 @@ query_tree_mutator(Query *query,
  */
 List *
 range_table_mutator(List *rtable,
-					Node *(*mutator) (),
+					tree_mutator_callback mutator,
 					void *context,
 					int flags)
 {
@@ -3526,7 +3517,7 @@ range_table_mutator(List *rtable,
  */
 bool
 query_or_expression_tree_walker(Node *node,
-								bool (*walker) (),
+								tree_walker_callback walker,
 								void *context,
 								int flags)
 {
@@ -3536,7 +3527,7 @@ query_or_expression_tree_walker(Node *node,
 								 context,
 								 flags);
 	else
-		return walker(node, context);
+		return WALK(node);
 }
 
 /*
@@ -3549,7 +3540,7 @@ query_or_expression_tree_walker(Node *node,
  */
 Node *
 query_or_expression_tree_mutator(Node *node,
-								 Node *(*mutator) (),
+								 tree_mutator_callback mutator,
 								 void *context,
 								 int flags)
 {
@@ -3580,7 +3571,7 @@ query_or_expression_tree_mutator(Node *node,
  */
 bool
 raw_expression_tree_walker(Node *node,
-						   bool (*walker) (),
+						   tree_walker_callback walker,
 						   void *context)
 {
 	ListCell   *temp;
@@ -3614,17 +3605,17 @@ raw_expression_tree_walker(Node *node,
 			/* we assume the colnames list isn't interesting */
 			break;
 		case T_RangeVar:
-			return walker(((RangeVar *) node)->alias, context);
+			return WALK(((RangeVar *) node)->alias);
 		case T_GroupingFunc:
-			return walker(((GroupingFunc *) node)->args, context);
+			return WALK(((GroupingFunc *) node)->args);
 		case T_SubLink:
 			{
 				SubLink    *sublink = (SubLink *) node;
 
-				if (walker(sublink->testexpr, context))
+				if (WALK(sublink->testexpr))
 					return true;
 				/* we assume the operName is not interesting */
-				if (walker(sublink->subselect, context))
+				if (WALK(sublink->subselect))
 					return true;
 			}
 			break;
@@ -3632,55 +3623,55 @@ raw_expression_tree_walker(Node *node,
 			{
 				CaseExpr   *caseexpr = (CaseExpr *) node;
 
-				if (walker(caseexpr->arg, context))
+				if (WALK(caseexpr->arg))
 					return true;
 				/* we assume walker doesn't care about CaseWhens, either */
 				foreach(temp, caseexpr->args)
 				{
 					CaseWhen   *when = lfirst_node(CaseWhen, temp);
 
-					if (walker(when->expr, context))
+					if (WALK(when->expr))
 						return true;
-					if (walker(when->result, context))
+					if (WALK(when->result))
 						return true;
 				}
-				if (walker(caseexpr->defresult, context))
+				if (WALK(caseexpr->defresult))
 					return true;
 			}
 			break;
 		case T_RowExpr:
 			/* Assume colnames isn't interesting */
-			return walker(((RowExpr *) node)->args, context);
+			return WALK(((RowExpr *) node)->args);
 		case T_CoalesceExpr:
-			return walker(((CoalesceExpr *) node)->args, context);
+			return WALK(((CoalesceExpr *) node)->args);
 		case T_MinMaxExpr:
-			return walker(((MinMaxExpr *) node)->args, context);
+			return WALK(((MinMaxExpr *) node)->args);
 		case T_XmlExpr:
 			{
 				XmlExpr    *xexpr = (XmlExpr *) node;
 
-				if (walker(xexpr->named_args, context))
+				if (WALK(xexpr->named_args))
 					return true;
 				/* we assume walker doesn't care about arg_names */
-				if (walker(xexpr->args, context))
+				if (WALK(xexpr->args))
 					return true;
 			}
 			break;
 		case T_NullTest:
-			return walker(((NullTest *) node)->arg, context);
+			return WALK(((NullTest *) node)->arg);
 		case T_BooleanTest:
-			return walker(((BooleanTest *) node)->arg, context);
+			return WALK(((BooleanTest *) node)->arg);
 		case T_JoinExpr:
 			{
 				JoinExpr   *join = (JoinExpr *) node;
 
-				if (walker(join->larg, context))
+				if (WALK(join->larg))
 					return true;
-				if (walker(join->rarg, context))
+				if (WALK(join->rarg))
 					return true;
-				if (walker(join->quals, context))
+				if (WALK(join->quals))
 					return true;
-				if (walker(join->alias, context))
+				if (WALK(join->alias))
 					return true;
 				/* using list is deemed uninteresting */
 			}
@@ -3689,18 +3680,18 @@ raw_expression_tree_walker(Node *node,
 			{
 				IntoClause *into = (IntoClause *) node;
 
-				if (walker(into->rel, context))
+				if (WALK(into->rel))
 					return true;
 				/* colNames, options are deemed uninteresting */
 				/* viewQuery should be null in raw parsetree, but check it */
-				if (walker(into->viewQuery, context))
+				if (WALK(into->viewQuery))
 					return true;
 			}
 			break;
 		case T_List:
 			foreach(temp, (List *) node)
 			{
-				if (walker((Node *) lfirst(temp), context))
+				if (WALK((Node *) lfirst(temp)))
 					return true;
 			}
 			break;
@@ -3708,17 +3699,17 @@ raw_expression_tree_walker(Node *node,
 			{
 				InsertStmt *stmt = (InsertStmt *) node;
 
-				if (walker(stmt->relation, context))
+				if (WALK(stmt->relation))
 					return true;
-				if (walker(stmt->cols, context))
+				if (WALK(stmt->cols))
 					return true;
-				if (walker(stmt->selectStmt, context))
+				if (WALK(stmt->selectStmt))
 					return true;
-				if (walker(stmt->onConflictClause, context))
+				if (WALK(stmt->onConflictClause))
 					return true;
-				if (walker(stmt->returningList, context))
+				if (WALK(stmt->returningList))
 					return true;
-				if (walker(stmt->withClause, context))
+				if (WALK(stmt->withClause))
 					return true;
 			}
 			break;
@@ -3726,15 +3717,15 @@ raw_expression_tree_walker(Node *node,
 			{
 				DeleteStmt *stmt = (DeleteStmt *) node;
 
-				if (walker(stmt->relation, context))
+				if (WALK(stmt->relation))
 					return true;
-				if (walker(stmt->usingClause, context))
+				if (WALK(stmt->usingClause))
 					return true;
-				if (walker(stmt->whereClause, context))
+				if (WALK(stmt->whereClause))
 					return true;
-				if (walker(stmt->returningList, context))
+				if (WALK(stmt->returningList))
 					return true;
-				if (walker(stmt->withClause, context))
+				if (WALK(stmt->withClause))
 					return true;
 			}
 			break;
@@ -3742,17 +3733,17 @@ raw_expression_tree_walker(Node *node,
 			{
 				UpdateStmt *stmt = (UpdateStmt *) node;
 
-				if (walker(stmt->relation, context))
+				if (WALK(stmt->relation))
 					return true;
-				if (walker(stmt->targetList, context))
+				if (WALK(stmt->targetList))
 					return true;
-				if (walker(stmt->whereClause, context))
+				if (WALK(stmt->whereClause))
 					return true;
-				if (walker(stmt->fromClause, context))
+				if (WALK(stmt->fromClause))
 					return true;
-				if (walker(stmt->returningList, context))
+				if (WALK(stmt->returningList))
 					return true;
-				if (walker(stmt->withClause, context))
+				if (WALK(stmt->withClause))
 					return true;
 			}
 			break;
@@ -3760,15 +3751,15 @@ raw_expression_tree_walker(Node *node,
 			{
 				MergeStmt  *stmt = (MergeStmt *) node;
 
-				if (walker(stmt->relation, context))
+				if (WALK(stmt->relation))
 					return true;
-				if (walker(stmt->sourceRelation, context))
+				if (WALK(stmt->sourceRelation))
 					return true;
-				if (walker(stmt->joinCondition, context))
+				if (WALK(stmt->joinCondition))
 					return true;
-				if (walker(stmt->mergeWhenClauses, context))
+				if (WALK(stmt->mergeWhenClauses))
 					return true;
-				if (walker(stmt->withClause, context))
+				if (WALK(stmt->withClause))
 					return true;
 			}
 			break;
@@ -3776,11 +3767,11 @@ raw_expression_tree_walker(Node *node,
 			{
 				MergeWhenClause *mergeWhenClause = (MergeWhenClause *) node;
 
-				if (walker(mergeWhenClause->condition, context))
+				if (WALK(mergeWhenClause->condition))
 					return true;
-				if (walker(mergeWhenClause->targetList, context))
+				if (WALK(mergeWhenClause->targetList))
 					return true;
-				if (walker(mergeWhenClause->values, context))
+				if (WALK(mergeWhenClause->values))
 					return true;
 			}
 			break;
@@ -3788,37 +3779,37 @@ raw_expression_tree_walker(Node *node,
 			{
 				SelectStmt *stmt = (SelectStmt *) node;
 
-				if (walker(stmt->distinctClause, context))
+				if (WALK(stmt->distinctClause))
 					return true;
-				if (walker(stmt->intoClause, context))
+				if (WALK(stmt->intoClause))
 					return true;
-				if (walker(stmt->targetList, context))
+				if (WALK(stmt->targetList))
 					return true;
-				if (walker(stmt->fromClause, context))
+				if (WALK(stmt->fromClause))
 					return true;
-				if (walker(stmt->whereClause, context))
+				if (WALK(stmt->whereClause))
 					return true;
-				if (walker(stmt->groupClause, context))
+				if (WALK(stmt->groupClause))
 					return true;
-				if (walker(stmt->havingClause, context))
+				if (WALK(stmt->havingClause))
 					return true;
-				if (walker(stmt->windowClause, context))
+				if (WALK(stmt->windowClause))
 					return true;
-				if (walker(stmt->valuesLists, context))
+				if (WALK(stmt->valuesLists))
 					return true;
-				if (walker(stmt->sortClause, context))
+				if (WALK(stmt->sortClause))
 					return true;
-				if (walker(stmt->limitOffset, context))
+				if (WALK(stmt->limitOffset))
 					return true;
-				if (walker(stmt->limitCount, context))
+				if (WALK(stmt->limitCount))
 					return true;
-				if (walker(stmt->lockingClause, context))
+				if (WALK(stmt->lockingClause))
 					return true;
-				if (walker(stmt->withClause, context))
+				if (WALK(stmt->withClause))
 					return true;
-				if (walker(stmt->larg, context))
+				if (WALK(stmt->larg))
 					return true;
-				if (walker(stmt->rarg, context))
+				if (WALK(stmt->rarg))
 					return true;
 			}
 			break;
@@ -3826,9 +3817,9 @@ raw_expression_tree_walker(Node *node,
 			{
 				PLAssignStmt *stmt = (PLAssignStmt *) node;
 
-				if (walker(stmt->indirection, context))
+				if (WALK(stmt->indirection))
 					return true;
-				if (walker(stmt->val, context))
+				if (WALK(stmt->val))
 					return true;
 			}
 			break;
@@ -3836,9 +3827,9 @@ raw_expression_tree_walker(Node *node,
 			{
 				A_Expr	   *expr = (A_Expr *) node;
 
-				if (walker(expr->lexpr, context))
+				if (WALK(expr->lexpr))
 					return true;
-				if (walker(expr->rexpr, context))
+				if (WALK(expr->rexpr))
 					return true;
 				/* operator name is deemed uninteresting */
 			}
@@ -3847,7 +3838,7 @@ raw_expression_tree_walker(Node *node,
 			{
 				BoolExpr   *expr = (BoolExpr *) node;
 
-				if (walker(expr->args, context))
+				if (WALK(expr->args))
 					return true;
 			}
 			break;
@@ -3858,26 +3849,26 @@ raw_expression_tree_walker(Node *node,
 			{
 				FuncCall   *fcall = (FuncCall *) node;
 
-				if (walker(fcall->args, context))
+				if (WALK(fcall->args))
 					return true;
-				if (walker(fcall->agg_order, context))
+				if (WALK(fcall->agg_order))
 					return true;
-				if (walker(fcall->agg_filter, context))
+				if (WALK(fcall->agg_filter))
 					return true;
-				if (walker(fcall->over, context))
+				if (WALK(fcall->over))
 					return true;
 				/* function name is deemed uninteresting */
 			}
 			break;
 		case T_NamedArgExpr:
-			return walker(((NamedArgExpr *) node)->arg, context);
+			return WALK(((NamedArgExpr *) node)->arg);
 		case T_A_Indices:
 			{
 				A_Indices  *indices = (A_Indices *) node;
 
-				if (walker(indices->lidx, context))
+				if (WALK(indices->lidx))
 					return true;
-				if (walker(indices->uidx, context))
+				if (WALK(indices->uidx))
 					return true;
 			}
 			break;
@@ -3885,51 +3876,51 @@ raw_expression_tree_walker(Node *node,
 			{
 				A_Indirection *indir = (A_Indirection *) node;
 
-				if (walker(indir->arg, context))
+				if (WALK(indir->arg))
 					return true;
-				if (walker(indir->indirection, context))
+				if (WALK(indir->indirection))
 					return true;
 			}
 			break;
 		case T_A_ArrayExpr:
-			return walker(((A_ArrayExpr *) node)->elements, context);
+			return WALK(((A_ArrayExpr *) node)->elements);
 		case T_ResTarget:
 			{
 				ResTarget  *rt = (ResTarget *) node;
 
-				if (walker(rt->indirection, context))
+				if (WALK(rt->indirection))
 					return true;
-				if (walker(rt->val, context))
+				if (WALK(rt->val))
 					return true;
 			}
 			break;
 		case T_MultiAssignRef:
-			return walker(((MultiAssignRef *) node)->source, context);
+			return WALK(((MultiAssignRef *) node)->source);
 		case T_TypeCast:
 			{
 				TypeCast   *tc = (TypeCast *) node;
 
-				if (walker(tc->arg, context))
+				if (WALK(tc->arg))
 					return true;
-				if (walker(tc->typeName, context))
+				if (WALK(tc->typeName))
 					return true;
 			}
 			break;
 		case T_CollateClause:
-			return walker(((CollateClause *) node)->arg, context);
+			return WALK(((CollateClause *) node)->arg);
 		case T_SortBy:
-			return walker(((SortBy *) node)->node, context);
+			return WALK(((SortBy *) node)->node);
 		case T_WindowDef:
 			{
 				WindowDef  *wd = (WindowDef *) node;
 
-				if (walker(wd->partitionClause, context))
+				if (WALK(wd->partitionClause))
 					return true;
-				if (walker(wd->orderClause, context))
+				if (WALK(wd->orderClause))
 					return true;
-				if (walker(wd->startOffset, context))
+				if (WALK(wd->startOffset))
 					return true;
-				if (walker(wd->endOffset, context))
+				if (WALK(wd->endOffset))
 					return true;
 			}
 			break;
@@ -3937,9 +3928,9 @@ raw_expression_tree_walker(Node *node,
 			{
 				RangeSubselect *rs = (RangeSubselect *) node;
 
-				if (walker(rs->subquery, context))
+				if (WALK(rs->subquery))
 					return true;
-				if (walker(rs->alias, context))
+				if (WALK(rs->alias))
 					return true;
 			}
 			break;
@@ -3947,11 +3938,11 @@ raw_expression_tree_walker(Node *node,
 			{
 				RangeFunction *rf = (RangeFunction *) node;
 
-				if (walker(rf->functions, context))
+				if (WALK(rf->functions))
 					return true;
-				if (walker(rf->alias, context))
+				if (WALK(rf->alias))
 					return true;
-				if (walker(rf->coldeflist, context))
+				if (WALK(rf->coldeflist))
 					return true;
 			}
 			break;
@@ -3959,12 +3950,12 @@ raw_expression_tree_walker(Node *node,
 			{
 				RangeTableSample *rts = (RangeTableSample *) node;
 
-				if (walker(rts->relation, context))
+				if (WALK(rts->relation))
 					return true;
 				/* method name is deemed uninteresting */
-				if (walker(rts->args, context))
+				if (WALK(rts->args))
 					return true;
-				if (walker(rts->repeatable, context))
+				if (WALK(rts->repeatable))
 					return true;
 			}
 			break;
@@ -3972,15 +3963,15 @@ raw_expression_tree_walker(Node *node,
 			{
 				RangeTableFunc *rtf = (RangeTableFunc *) node;
 
-				if (walker(rtf->docexpr, context))
+				if (WALK(rtf->docexpr))
 					return true;
-				if (walker(rtf->rowexpr, context))
+				if (WALK(rtf->rowexpr))
 					return true;
-				if (walker(rtf->namespaces, context))
+				if (WALK(rtf->namespaces))
 					return true;
-				if (walker(rtf->columns, context))
+				if (WALK(rtf->columns))
 					return true;
-				if (walker(rtf->alias, context))
+				if (WALK(rtf->alias))
 					return true;
 			}
 			break;
@@ -3988,9 +3979,9 @@ raw_expression_tree_walker(Node *node,
 			{
 				RangeTableFuncCol *rtfc = (RangeTableFuncCol *) node;
 
-				if (walker(rtfc->colexpr, context))
+				if (WALK(rtfc->colexpr))
 					return true;
-				if (walker(rtfc->coldefexpr, context))
+				if (WALK(rtfc->coldefexpr))
 					return true;
 			}
 			break;
@@ -3998,9 +3989,9 @@ raw_expression_tree_walker(Node *node,
 			{
 				TypeName   *tn = (TypeName *) node;
 
-				if (walker(tn->typmods, context))
+				if (WALK(tn->typmods))
 					return true;
-				if (walker(tn->arrayBounds, context))
+				if (WALK(tn->arrayBounds))
 					return true;
 				/* type name itself is deemed uninteresting */
 			}
@@ -4009,13 +4000,13 @@ raw_expression_tree_walker(Node *node,
 			{
 				ColumnDef  *coldef = (ColumnDef *) node;
 
-				if (walker(coldef->typeName, context))
+				if (WALK(coldef->typeName))
 					return true;
-				if (walker(coldef->compression, context))
+				if (WALK(coldef->compression))
 					return true;
-				if (walker(coldef->raw_default, context))
+				if (WALK(coldef->raw_default))
 					return true;
-				if (walker(coldef->collClause, context))
+				if (WALK(coldef->collClause))
 					return true;
 				/* for now, constraints are ignored */
 			}
@@ -4024,34 +4015,34 @@ raw_expression_tree_walker(Node *node,
 			{
 				IndexElem  *indelem = (IndexElem *) node;
 
-				if (walker(indelem->expr, context))
+				if (WALK(indelem->expr))
 					return true;
 				/* collation and opclass names are deemed uninteresting */
 			}
 			break;
 		case T_GroupingSet:
-			return walker(((GroupingSet *) node)->content, context);
+			return WALK(((GroupingSet *) node)->content);
 		case T_LockingClause:
-			return walker(((LockingClause *) node)->lockedRels, context);
+			return WALK(((LockingClause *) node)->lockedRels);
 		case T_XmlSerialize:
 			{
 				XmlSerialize *xs = (XmlSerialize *) node;
 
-				if (walker(xs->expr, context))
+				if (WALK(xs->expr))
 					return true;
-				if (walker(xs->typeName, context))
+				if (WALK(xs->typeName))
 					return true;
 			}
 			break;
 		case T_WithClause:
-			return walker(((WithClause *) node)->ctes, context);
+			return WALK(((WithClause *) node)->ctes);
 		case T_InferClause:
 			{
 				InferClause *stmt = (InferClause *) node;
 
-				if (walker(stmt->indexElems, context))
+				if (WALK(stmt->indexElems))
 					return true;
-				if (walker(stmt->whereClause, context))
+				if (WALK(stmt->whereClause))
 					return true;
 			}
 			break;
@@ -4059,17 +4050,17 @@ raw_expression_tree_walker(Node *node,
 			{
 				OnConflictClause *stmt = (OnConflictClause *) node;
 
-				if (walker(stmt->infer, context))
+				if (WALK(stmt->infer))
 					return true;
-				if (walker(stmt->targetList, context))
+				if (WALK(stmt->targetList))
 					return true;
-				if (walker(stmt->whereClause, context))
+				if (WALK(stmt->whereClause))
 					return true;
 			}
 			break;
 		case T_CommonTableExpr:
 			/* search_clause and cycle_clause are not interesting here */
-			return walker(((CommonTableExpr *) node)->ctequery, context);
+			return WALK(((CommonTableExpr *) node)->ctequery);
 		default:
 			elog(ERROR, "unrecognized node type: %d",
 				 (int) nodeTag(node));
@@ -4086,7 +4077,7 @@ raw_expression_tree_walker(Node *node,
  */
 bool
 planstate_tree_walker(PlanState *planstate,
-					  bool (*walker) (),
+					  tree_walker_callback walker,
 					  void *context)
 {
 	Plan	   *plan = planstate->plan;
@@ -4102,14 +4093,14 @@ planstate_tree_walker(PlanState *planstate,
 	/* lefttree */
 	if (outerPlanState(planstate))
 	{
-		if (walker(outerPlanState(planstate), context))
+		if (WALK(outerPlanState(planstate)))
 			return true;
 	}
 
 	/* righttree */
 	if (innerPlanState(planstate))
 	{
-		if (walker(innerPlanState(planstate), context))
+		if (WALK(innerPlanState(planstate)))
 			return true;
 	}
 
@@ -4141,13 +4132,13 @@ planstate_tree_walker(PlanState *planstate,
 				return true;
 			break;
 		case T_SubqueryScan:
-			if (walker(((SubqueryScanState *) planstate)->subplan, context))
+			if (WALK(((SubqueryScanState *) planstate)->subplan))
 				return true;
 			break;
 		case T_CustomScan:
 			foreach(lc, ((CustomScanState *) planstate)->custom_ps)
 			{
-				if (walker((PlanState *) lfirst(lc), context))
+				if (WALK(lfirst(lc)))
 					return true;
 			}
 			break;
@@ -4167,7 +4158,7 @@ planstate_tree_walker(PlanState *planstate,
  */
 static bool
 planstate_walk_subplans(List *plans,
-						bool (*walker) (),
+						tree_walker_callback walker,
 						void *context)
 {
 	ListCell   *lc;
@@ -4176,7 +4167,7 @@ planstate_walk_subplans(List *plans,
 	{
 		SubPlanState *sps = lfirst_node(SubPlanState, lc);
 
-		if (walker(sps->planstate, context))
+		if (WALK(sps->planstate))
 			return true;
 	}
 
@@ -4189,13 +4180,13 @@ planstate_walk_subplans(List *plans,
  */
 static bool
 planstate_walk_members(PlanState **planstates, int nplans,
-					   bool (*walker) (), void *context)
+					   tree_walker_callback walker, void *context)
 {
 	int			j;
 
 	for (j = 0; j < nplans; j++)
 	{
-		if (walker(planstates[j], context))
+		if (WALK(planstates[j]))
 			return true;
 	}
 
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index f486d42441..9ba3ad93b7 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -165,7 +165,7 @@ static MergeScanSelCache *cached_scansel(PlannerInfo *root,
 										 PathKey *pathkey);
 static void cost_rescan(PlannerInfo *root, Path *path,
 						Cost *rescan_startup_cost, Cost *rescan_total_cost);
-static bool cost_qual_eval_walker(Node *node, cost_qual_eval_context *context);
+static bool cost_qual_eval_walker(Node *node, void *ctx);
 static void get_restriction_qual_cost(PlannerInfo *root, RelOptInfo *baserel,
 									  ParamPathInfo *param_info,
 									  QualCost *qpqual_cost);
@@ -4722,8 +4722,10 @@ cost_qual_eval_node(QualCost *cost, Node *qual, PlannerInfo *root)
 }
 
 static bool
-cost_qual_eval_walker(Node *node, cost_qual_eval_context *context)
+cost_qual_eval_walker(Node *node, void *ctx)
 {
+	cost_qual_eval_context *context = (cost_qual_eval_context *) ctx;
+
 	if (node == NULL)
 		return false;
 
diff --git a/src/include/nodes/nodeFuncs.h b/src/include/nodes/nodeFuncs.h
index 93c60bde66..cb92a9de66 100644
--- a/src/include/nodes/nodeFuncs.h
+++ b/src/include/nodes/nodeFuncs.h
@@ -32,6 +32,12 @@
 /* callback function for check_functions_in_node */
 typedef bool (*check_function_callback) (Oid func_id, void *context);
 
+/* callback functions for tree walkers */
+typedef bool (*tree_walker_callback) (Node *node, void *context);
+
+/* callback functions for tree mutators */
+typedef Node *(*tree_mutator_callback) (Node *node, void *context);
+
 
 extern Oid	exprType(const Node *expr);
 extern int32 exprTypmod(const Node *expr);
@@ -129,34 +135,39 @@ get_notclausearg(const void *notclause)
 extern bool check_functions_in_node(Node *node, check_function_callback checker,
 									void *context);
 
-extern bool expression_tree_walker(Node *node, bool (*walker) (),
+extern bool expression_tree_walker(Node *node, tree_walker_callback walker,
 								   void *context);
-extern Node *expression_tree_mutator(Node *node, Node *(*mutator) (),
+extern Node *expression_tree_mutator(Node *node, tree_mutator_callback mutator,
 									 void *context);
 
-extern bool query_tree_walker(Query *query, bool (*walker) (),
+extern bool query_tree_walker(Query *query, tree_walker_callback walker,
 							  void *context, int flags);
-extern Query *query_tree_mutator(Query *query, Node *(*mutator) (),
+extern Query *query_tree_mutator(Query *query, tree_mutator_callback mutator,
 								 void *context, int flags);
 
-extern bool range_table_walker(List *rtable, bool (*walker) (),
+extern bool range_table_walker(List *rtable, tree_walker_callback walker,
 							   void *context, int flags);
-extern List *range_table_mutator(List *rtable, Node *(*mutator) (),
+extern List *range_table_mutator(List *rtable, tree_mutator_callback mutator,
 								 void *context, int flags);
 
-extern bool range_table_entry_walker(RangeTblEntry *rte, bool (*walker) (),
+extern bool range_table_entry_walker(RangeTblEntry *rte,
+									 tree_walker_callback walker,
 									 void *context, int flags);
 
-extern bool query_or_expression_tree_walker(Node *node, bool (*walker) (),
+extern bool query_or_expression_tree_walker(Node *node,
+											tree_walker_callback walker,
 											void *context, int flags);
-extern Node *query_or_expression_tree_mutator(Node *node, Node *(*mutator) (),
+extern Node *query_or_expression_tree_mutator(Node *node,
+											  tree_mutator_callback mutator,
 											  void *context, int flags);
 
-extern bool raw_expression_tree_walker(Node *node, bool (*walker) (),
+extern bool raw_expression_tree_walker(Node *node,
+									   tree_walker_callback walker,
 									   void *context);
 
 struct PlanState;
-extern bool planstate_tree_walker(struct PlanState *planstate, bool (*walker) (),
+extern bool planstate_tree_walker(struct PlanState *planstate,
+								  tree_walker_callback walker,
 								  void *context);
 
 #endif							/* NODEFUNCS_H */

---

From: Tom Lane <[email-masked]>
Date: Sun, 18 Sep 2022 16:57:45 -0400

> call sites if this way seems good to people.

Here's a fleshed-out patch that gets rid of all warnings of this sort
(tested on clang version 15.0.0).

While I remain happy enough with what has to be done in nodeFuncs.c,

> the appropriate kind of context struct.  Thanks, C committee.

There are a lot of these walker/mutator functions and hence a whole
lot of opportunity to pass the wrong thing, not only from the outer
non-recursive call points but during internal recursions in the
walkers/mutators themselves.

I think we ought to seriously consider the alternative of changing
nodeFuncs.c about like I have here, but not touching the walkers/mutators,
and silencing the resulting complaints about function type casting by
doing the equivalent of

-    return expression_tree_walker(node, cost_qual_eval_walker,
-                                  (void *) context);
+    return expression_tree_walker(node,
+                                  (tree_walker_callback) cost_qual_eval_walker,
+                                  (void *) context);

We could avoid touching all the call sites by turning
expression_tree_walker and friends into macro wrappers that incorporate
these casts.  This is fairly annoying, in that it gives up the function
type safety the C committee wants to impose on us; but I really think
the data type safety that we're giving up in this version of the patch
is a worse hazard.

BTW, I was distressed to discover that someone decided they could
use ExecShutdownNode as a planstate_tree_walker() walker even though
its argument list is not even the right length.  I'm a bit flabbergasted
that we seem to have gotten away with that so far, because I'd have
thought for sure that it'd break some platform's convention for which
argument gets passed where.  I think we need to fix that, independently
of what we do about the larger scope of these problems.  To avoid an
API break, I propose making ExecShutdownNode just be a one-liner that
calls an internal ExecShutdownNode_walker() function.  (I've not done
it that way in the attached, though.)

Thoughts?

			regards, tom lane

diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index 39768fa22b..f127f20fd8 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -206,8 +206,7 @@ static void reportDependentObjects(const ObjectAddresses *targetObjects,
 static void deleteOneObject(const ObjectAddress *object,
 							Relation *depRel, int32 flags);
 static void doDeletion(const ObjectAddress *object, int flags);
-static bool find_expr_references_walker(Node *node,
-										find_expr_references_context *context);
+static bool find_expr_references_walker(Node *node, void *ctx);
 static void process_function_rte_ref(RangeTblEntry *rte, AttrNumber attnum,
 									 find_expr_references_context *context);
 static void eliminate_duplicate_dependencies(ObjectAddresses *addrs);
@@ -1738,9 +1737,10 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
  * the collation is being freshly introduced to the expression.
  */
 static bool
-find_expr_references_walker(Node *node,
-							find_expr_references_context *context)
+find_expr_references_walker(Node *node, void *ctx)
 {
+	find_expr_references_context *context = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, Var))
@@ -2283,7 +2283,7 @@ find_expr_references_walker(Node *node,
 		context->rtables = lcons(query->rtable, context->rtables);
 		result = query_tree_walker(query,
 								   find_expr_references_walker,
-								   (void *) context,
+								   ctx,
 								   QTW_IGNORE_JOINALIASES |
 								   QTW_EXAMINE_SORTGROUP);
 		context->rtables = list_delete_first(context->rtables);
@@ -2352,8 +2352,7 @@ find_expr_references_walker(Node *node,
 		/* fall through to examine arguments */
 	}
 
-	return expression_tree_walker(node, find_expr_references_walker,
-								  (void *) context);
+	return expression_tree_walker(node, find_expr_references_walker, ctx);
 }
 
 /*
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 053d2ca5ae..671a41d3b6 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -63,7 +63,7 @@ static void ExplainPrintJIT(ExplainState *es, int jit_flags,
 static void report_triggers(ResultRelInfo *rInfo, bool show_relname,
 							ExplainState *es);
 static double elapsed_time(instr_time *starttime);
-static bool ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used);
+static bool ExplainPreScanNode(PlanState *planstate, void *ctx);
 static void ExplainNode(PlanState *planstate, List *ancestors,
 						const char *relationship, const char *plan_name,
 						ExplainState *es);
@@ -1089,8 +1089,9 @@ elapsed_time(instr_time *starttime)
  * that never appear in the EXPLAIN output (such as inheritance parents).
  */
 static bool
-ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
+ExplainPreScanNode(PlanState *planstate, void *ctx)
 {
+	Bitmapset **rels_used = ctx;
 	Plan	   *plan = planstate->plan;
 
 	switch (nodeTag(plan))
@@ -1139,7 +1140,7 @@ ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
 			break;
 	}
 
-	return planstate_tree_walker(planstate, ExplainPreScanNode, rels_used);
+	return planstate_tree_walker(planstate, ExplainPreScanNode, ctx);
 }
 
 /*
diff --git a/src/backend/commands/lockcmds.c b/src/backend/commands/lockcmds.c
index b97b8b0435..adaad13310 100644
--- a/src/backend/commands/lockcmds.c
+++ b/src/backend/commands/lockcmds.c
@@ -175,8 +175,10 @@ typedef struct
 } LockViewRecurse_context;
 
 static bool
-LockViewRecurse_walker(Node *node, LockViewRecurse_context *context)
+LockViewRecurse_walker(Node *node, void *ctx)
 {
+	LockViewRecurse_context *context = ctx;
+
 	if (node == NULL)
 		return false;
 
@@ -242,13 +244,11 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context)
 
 		return query_tree_walker(query,
 								 LockViewRecurse_walker,
-								 context,
+								 ctx,
 								 QTW_IGNORE_JOINALIASES);
 	}
 
-	return expression_tree_walker(node,
-								  LockViewRecurse_walker,
-								  context);
+	return expression_tree_walker(node, LockViewRecurse_walker, ctx);
 }
 
 static void
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 8b574b86c4..b84e841291 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -257,8 +257,10 @@ CheckObjSchemaNotAlreadyInPublication(List *rels, List *schemaidlist,
  * not part of REPLICA IDENTITY, false otherwise.
  */
 static bool
-contain_invalid_rfcolumn_walker(Node *node, rf_context *context)
+contain_invalid_rfcolumn_walker(Node *node, void *ctx)
 {
+	rf_context *context = ctx;
+
 	if (node == NULL)
 		return false;
 
@@ -285,8 +287,7 @@ contain_invalid_rfcolumn_walker(Node *node, rf_context *context)
 			return true;
 	}
 
-	return expression_tree_walker(node, contain_invalid_rfcolumn_walker,
-								  (void *) context);
+	return expression_tree_walker(node, contain_invalid_rfcolumn_walker, ctx);
 }
 
 /*
@@ -549,8 +550,9 @@ expr_allowed_in_node(Node *node, ParseState *pstate, char **errdetail_msg)
  * We can allow other node types after more analysis and testing.
  */
 static bool
-check_simple_rowfilter_expr_walker(Node *node, ParseState *pstate)
+check_simple_rowfilter_expr_walker(Node *node, void *ctx)
 {
+	ParseState *pstate = ctx;
 	char	   *errdetail_msg = NULL;
 
 	if (node == NULL)
@@ -632,8 +634,7 @@ check_simple_rowfilter_expr_walker(Node *node, ParseState *pstate)
 				 errdetail("%s", errdetail_msg),
 				 parser_errposition(pstate, exprLocation(node))));
 
-	return expression_tree_walker(node, check_simple_rowfilter_expr_walker,
-								  (void *) pstate);
+	return expression_tree_walker(node, check_simple_rowfilter_expr_walker, ctx);
 }
 
 /*
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index 25a94bbaaa..b4a6f360c1 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -66,7 +66,7 @@ static void ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args,
 						 ExprState *state);
 static void ExecInitExprSlots(ExprState *state, Node *node);
 static void ExecPushExprSlots(ExprState *state, LastAttnumInfo *info);
-static bool get_last_attnums_walker(Node *node, LastAttnumInfo *info);
+static bool get_last_attnums_walker(Node *node, void *ctx);
 static bool ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op);
 static void ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable,
 								ExprState *state);
@@ -2618,8 +2618,10 @@ ExecPushExprSlots(ExprState *state, LastAttnumInfo *info)
  * get_last_attnums_walker: expression walker for ExecInitExprSlots
  */
 static bool
-get_last_attnums_walker(Node *node, LastAttnumInfo *info)
+get_last_attnums_walker(Node *node, void *ctx)
 {
+	LastAttnumInfo *info = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, Var))
@@ -2658,8 +2660,7 @@ get_last_attnums_walker(Node *node, LastAttnumInfo *info)
 		return false;
 	if (IsA(node, GroupingFunc))
 		return false;
-	return expression_tree_walker(node, get_last_attnums_walker,
-								  (void *) info);
+	return expression_tree_walker(node, get_last_attnums_walker, ctx);
 }
 
 /*
diff --git a/src/backend/executor/execIndexing.c b/src/backend/executor/execIndexing.c
index 6a8735edf7..b6ea05f13a 100644
--- a/src/backend/executor/execIndexing.c
+++ b/src/backend/executor/execIndexing.c
@@ -139,8 +139,8 @@ static bool index_recheck_constraint(Relation index, Oid *constr_procs,
 static bool index_unchanged_by_update(ResultRelInfo *resultRelInfo,
 									  EState *estate, IndexInfo *indexInfo,
 									  Relation indexRelation);
-static bool index_expression_changed_walker(Node *node,
-											Bitmapset *allUpdatedCols);
+static bool index_expression_changed_walker(Node *node, void *ctx);
+
 
 /* ----------------------------------------------------------------
  *		ExecOpenIndices
@@ -1052,8 +1052,10 @@ index_unchanged_by_update(ResultRelInfo *resultRelInfo, EState *estate,
  * Returns true when Var that appears within allUpdatedCols located.
  */
 static bool
-index_expression_changed_walker(Node *node, Bitmapset *allUpdatedCols)
+index_expression_changed_walker(Node *node, void *ctx)
 {
+	Bitmapset  *allUpdatedCols = ctx;
+
 	if (node == NULL)
 		return false;
 
@@ -1072,6 +1074,5 @@ index_expression_changed_walker(Node *node, Bitmapset *allUpdatedCols)
 		return false;
 	}
 
-	return expression_tree_walker(node, index_expression_changed_walker,
-								  (void *) allUpdatedCols);
+	return expression_tree_walker(node, index_expression_changed_walker, ctx);
 }
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index ef2fd46092..e0b73da435 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -1691,7 +1691,7 @@ ExecutePlan(EState *estate,
 	 * point.
 	 */
 	if (!(estate->es_top_eflags & EXEC_FLAG_BACKWARD))
-		(void) ExecShutdownNode(planstate);
+		(void) ExecShutdownNode(planstate, NULL);
 
 	if (use_parallel_mode)
 		ExitParallelMode();
diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c
index f1fd7f7e8b..d7f402091f 100644
--- a/src/backend/executor/execParallel.c
+++ b/src/backend/executor/execParallel.c
@@ -126,16 +126,12 @@ typedef struct ExecParallelInitializeDSMContext
 
 /* Helper functions that run in the parallel leader. */
 static char *ExecSerializePlan(Plan *plan, EState *estate);
-static bool ExecParallelEstimate(PlanState *node,
-								 ExecParallelEstimateContext *e);
-static bool ExecParallelInitializeDSM(PlanState *node,
-									  ExecParallelInitializeDSMContext *d);
+static bool ExecParallelEstimate(PlanState *node, void *ctx);
+static bool ExecParallelInitializeDSM(PlanState *node, void *ctx);
 static shm_mq_handle **ExecParallelSetupTupleQueues(ParallelContext *pcxt,
 													bool reinitialize);
-static bool ExecParallelReInitializeDSM(PlanState *planstate,
-										ParallelContext *pcxt);
-static bool ExecParallelRetrieveInstrumentation(PlanState *planstate,
-												SharedExecutorInstrumentation *instrumentation);
+static bool ExecParallelReInitializeDSM(PlanState *planstate, void *ctx);
+static bool ExecParallelRetrieveInstrumentation(PlanState *planstate, void *ctx);
 
 /* Helper function that runs in the parallel worker. */
 static DestReceiver *ExecParallelGetReceiver(dsm_segment *seg, shm_toc *toc);
@@ -227,8 +223,10 @@ ExecSerializePlan(Plan *plan, EState *estate)
  * we know how many Instrumentation structures we need.
  */
 static bool
-ExecParallelEstimate(PlanState *planstate, ExecParallelEstimateContext *e)
+ExecParallelEstimate(PlanState *planstate, void *ctx)
 {
+	ExecParallelEstimateContext *e = ctx;
+
 	if (planstate == NULL)
 		return false;
 
@@ -301,7 +299,7 @@ ExecParallelEstimate(PlanState *planstate, ExecParallelEstimateContext *e)
 			break;
 	}
 
-	return planstate_tree_walker(planstate, ExecParallelEstimate, e);
+	return planstate_tree_walker(planstate, ExecParallelEstimate, ctx);
 }
 
 /*
@@ -436,9 +434,10 @@ RestoreParamExecParams(char *start_address, EState *estate)
  * parallel execution.
  */
 static bool
-ExecParallelInitializeDSM(PlanState *planstate,
-						  ExecParallelInitializeDSMContext *d)
+ExecParallelInitializeDSM(PlanState *planstate, void *ctx)
 {
+	ExecParallelInitializeDSMContext *d = ctx;
+
 	if (planstate == NULL)
 		return false;
 
@@ -525,7 +524,7 @@ ExecParallelInitializeDSM(PlanState *planstate,
 			break;
 	}
 
-	return planstate_tree_walker(planstate, ExecParallelInitializeDSM, d);
+	return planstate_tree_walker(planstate, ExecParallelInitializeDSM, ctx);
 }
 
 /*
@@ -944,9 +943,10 @@ ExecParallelReinitialize(PlanState *planstate,
  * Traverse plan tree to reinitialize per-node dynamic shared memory state
  */
 static bool
-ExecParallelReInitializeDSM(PlanState *planstate,
-							ParallelContext *pcxt)
+ExecParallelReInitializeDSM(PlanState *planstate, void *ctx)
 {
+	ParallelContext *pcxt = ctx;
+
 	if (planstate == NULL)
 		return false;
 
@@ -1005,7 +1005,7 @@ ExecParallelReInitializeDSM(PlanState *planstate,
 			break;
 	}
 
-	return planstate_tree_walker(planstate, ExecParallelReInitializeDSM, pcxt);
+	return planstate_tree_walker(planstate, ExecParallelReInitializeDSM, ctx);
 }
 
 /*
@@ -1013,9 +1013,9 @@ ExecParallelReInitializeDSM(PlanState *planstate,
  * dynamic shared memory.
  */
 static bool
-ExecParallelRetrieveInstrumentation(PlanState *planstate,
-									SharedExecutorInstrumentation *instrumentation)
+ExecParallelRetrieveInstrumentation(PlanState *planstate, void *ctx)
 {
+	SharedExecutorInstrumentation *instrumentation = ctx;
 	Instrumentation *instrument;
 	int			i;
 	int			n;
@@ -1075,7 +1075,7 @@ ExecParallelRetrieveInstrumentation(PlanState *planstate,
 	}
 
 	return planstate_tree_walker(planstate, ExecParallelRetrieveInstrumentation,
-								 instrumentation);
+								 ctx);
 }
 
 /*
@@ -1259,12 +1259,12 @@ ExecParallelGetQueryDesc(shm_toc *toc, DestReceiver *receiver,
  * dynamic shared memory, so that the parallel leader can retrieve it.
  */
 static bool
-ExecParallelReportInstrumentation(PlanState *planstate,
-								  SharedExecutorInstrumentation *instrumentation)
+ExecParallelReportInstrumentation(PlanState *planstate, void *ctx)
 {
-	int			i;
+	SharedExecutorInstrumentation *instrumentation = ctx;
 	int			plan_node_id = planstate->plan->plan_node_id;
 	Instrumentation *instrument;
+	int			i;
 
 	InstrEndLoop(planstate->instrument);
 
@@ -1291,7 +1291,7 @@ ExecParallelReportInstrumentation(PlanState *planstate,
 	InstrAggNode(&instrument[ParallelWorkerNumber], planstate->instrument);
 
 	return planstate_tree_walker(planstate, ExecParallelReportInstrumentation,
-								 instrumentation);
+								 ctx);
 }
 
 /*
@@ -1300,8 +1300,10 @@ ExecParallelReportInstrumentation(PlanState *planstate,
  * is allocated and initialized by executor; that is, after ExecutorStart().
  */
 static bool
-ExecParallelInitializeWorker(PlanState *planstate, ParallelWorkerContext *pwcxt)
+ExecParallelInitializeWorker(PlanState *planstate, void *ctx)
 {
+	ParallelWorkerContext *pwcxt = ctx;
+
 	if (planstate == NULL)
 		return false;
 
@@ -1370,8 +1372,7 @@ ExecParallelInitializeWorker(PlanState *planstate, ParallelWorkerContext *pwcxt)
 			break;
 	}
 
-	return planstate_tree_walker(planstate, ExecParallelInitializeWorker,
-								 pwcxt);
+	return planstate_tree_walker(planstate, ExecParallelInitializeWorker, ctx);
 }
 
 /*
diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c
index b5667e53e5..18d9096be0 100644
--- a/src/backend/executor/execProcnode.c
+++ b/src/backend/executor/execProcnode.c
@@ -769,7 +769,7 @@ ExecEndNode(PlanState *node)
  * and release any resources still held.
  */
 bool
-ExecShutdownNode(PlanState *node)
+ExecShutdownNode(PlanState *node, void *ctx)
 {
 	if (node == NULL)
 		return false;
@@ -789,7 +789,7 @@ ExecShutdownNode(PlanState *node)
 	if (node->instrument && node->instrument->running)
 		InstrStartNode(node->instrument);
 
-	planstate_tree_walker(node, ExecShutdownNode, NULL);
+	planstate_tree_walker(node, ExecShutdownNode, ctx);
 
 	switch (nodeTag(node))
 	{
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 933c304901..1e31fe74e9 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -401,7 +401,7 @@ static void finalize_aggregates(AggState *aggstate,
 static TupleTableSlot *project_aggregates(AggState *aggstate);
 static void find_cols(AggState *aggstate, Bitmapset **aggregated,
 					  Bitmapset **unaggregated);
-static bool find_cols_walker(Node *node, FindColsContext *context);
+static bool find_cols_walker(Node *node, void *ctx);
 static void build_hash_tables(AggState *aggstate);
 static void build_hash_table(AggState *aggstate, int setno, long nbuckets);
 static void hashagg_recompile_expressions(AggState *aggstate, bool minslot,
@@ -1414,8 +1414,10 @@ find_cols(AggState *aggstate, Bitmapset **aggregated, Bitmapset **unaggregated)
 }
 
 static bool
-find_cols_walker(Node *node, FindColsContext *context)
+find_cols_walker(Node *node, void *ctx)
 {
+	FindColsContext *context = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, Var))
@@ -1437,12 +1439,11 @@ find_cols_walker(Node *node, FindColsContext *context)
 	{
 		Assert(!context->is_aggref);
 		context->is_aggref = true;
-		expression_tree_walker(node, find_cols_walker, (void *) context);
+		expression_tree_walker(node, find_cols_walker, ctx);
 		context->is_aggref = false;
 		return false;
 	}
-	return expression_tree_walker(node, find_cols_walker,
-								  (void *) context);
+	return expression_tree_walker(node, find_cols_walker, ctx);
 }
 
 /*
diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c
index 3bac350bf5..06363dab40 100644
--- a/src/backend/nodes/nodeFuncs.c
+++ b/src/backend/nodes/nodeFuncs.c
@@ -27,10 +27,12 @@
 static bool expression_returns_set_walker(Node *node, void *context);
 static int	leftmostLoc(int loc1, int loc2);
 static bool fix_opfuncids_walker(Node *node, void *context);
-static bool planstate_walk_subplans(List *plans, bool (*walker) (),
+static bool planstate_walk_subplans(List *plans,
+									planstate_tree_walker_callback walker,
 									void *context);
 static bool planstate_walk_members(PlanState **planstates, int nplans,
-								   bool (*walker) (), void *context);
+								   planstate_tree_walker_callback walker,
+								   void *context);

 /*
@@ -1836,7 +1838,7 @@ check_functions_in_node(Node *node, check_function_callback checker,
  * that modify nodes in-place but never add/delete/replace nodes).
  * A walker routine should look like this:
  *
- * bool my_walker (Node *node, my_struct *context)
+ * bool my_walker (Node *node, void *context)
  * {
  *		if (node == NULL)
  *			return false;
@@ -1850,7 +1852,7 @@ check_functions_in_node(Node *node, check_function_callback checker,
  *			... do special actions for other node types
  *		}
  *		// for any node type not specially processed, do:
- *		return expression_tree_walker(node, my_walker, (void *) context);
+ *		return expression_tree_walker(node, my_walker, context);
  * }
  *
  * The "context" argument points to a struct that holds whatever context
@@ -1910,7 +1912,7 @@ check_functions_in_node(Node *node, check_function_callback checker,
 
 bool
@@ -1923,6 +1925,10 @@ expression_tree_walker(Node *node,
 
@@ -1946,25 +1952,21 @@ expression_tree_walker(Node *node,
 
@@ -1972,8 +1974,7 @@ expression_tree_walker(Node *node,
 
-				if (expression_tree_walker((Node *) grouping->args,
-										   walker, context))
+				if (LIST_WALK(grouping->args))
 					return true;
 			}
 			break;
@@ -1982,10 +1983,9 @@ expression_tree_walker(Node *node,
 				WindowFunc *expr = (WindowFunc *) node;
 
@@ -1994,17 +1994,15 @@ expression_tree_walker(Node *node,

-				if (walker(sbsref->refassgnexpr, context))
+				if (WALK(sbsref->refassgnexpr))
 					return true;
 			}
 			break;
@@ -2012,21 +2010,19 @@ expression_tree_walker(Node *node,
 			{
 				FuncExpr   *expr = (FuncExpr *) node;

-				if (expression_tree_walker((Node *) expr->args,
-										   walker, context))
+				if (LIST_WALK(expr->args))
 					return true;
 			}
 			break;
@@ -2034,8 +2030,7 @@ expression_tree_walker(Node *node,
 			{
 				ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
 
-				if (expression_tree_walker((Node *) expr->args,
-										   walker, context))
+				if (LIST_WALK(expr->args))
 					return true;
 			}
 			break;
@@ -2043,8 +2038,7 @@ expression_tree_walker(Node *node,
 			{
 				BoolExpr   *expr = (BoolExpr *) node;
 
-				if (expression_tree_walker((Node *) expr->args,
-										   walker, context))
+				if (LIST_WALK(expr->args))
 					return true;
 			}
 			break;
@@ -2052,14 +2046,14 @@ expression_tree_walker(Node *node,
 			{
 				SubLink    *sublink = (SubLink *) node;

 				/*
@@ -2067,104 +2061,103 @@ expression_tree_walker(Node *node,

 

 
 
@@ -2172,13 +2165,13 @@ expression_tree_walker(Node *node,
 
@@ -2186,9 +2179,9 @@ expression_tree_walker(Node *node,
 
@@ -2200,12 +2193,12 @@ expression_tree_walker(Node *node,
 
@@ -2213,11 +2206,11 @@ expression_tree_walker(Node *node,
 
@@ -2225,14 +2218,14 @@ expression_tree_walker(Node *node,
 
@@ -2240,9 +2233,9 @@ expression_tree_walker(Node *node,
 
@@ -2250,15 +2243,15 @@ expression_tree_walker(Node *node,
 
@@ -2266,9 +2259,9 @@ expression_tree_walker(Node *node,
 
@@ -2276,7 +2269,7 @@ expression_tree_walker(Node *node,
 
-				if (walker((Node *) opstep->exprs, context))
+				if (WALK(opstep->exprs))
 					return true;
 			}
 			break;
@@ -2287,11 +2280,11 @@ expression_tree_walker(Node *node,
 			{
 				JoinExpr   *join = (JoinExpr *) node;

 				/*
@@ -2303,9 +2296,9 @@ expression_tree_walker(Node *node,
 			{
 				SetOperationStmt *setop = (SetOperationStmt *) node;

 				/* groupClauses are deemed uninteresting */
@@ -2315,38 +2308,35 @@ expression_tree_walker(Node *node,
 			{
 				IndexClause *iclause = (IndexClause *) node;

 
@@ -2354,15 +2344,15 @@ expression_tree_walker(Node *node,
 
@@ -2372,6 +2362,9 @@ expression_tree_walker(Node *node,
 
 /*
@@ -2391,7 +2384,7 @@ expression_tree_walker(Node *node,
  */
 bool
 query_tree_walker(Query *query,
-				  bool (*walker) (),
+				  tree_walker_callback walker,
 				  void *context,
 				  int flags)
 {
@@ -2404,25 +2397,25 @@ query_tree_walker(Query *query,
 	 * in a rule action.
 	 */

 	/*
@@ -2432,13 +2425,13 @@ query_tree_walker(Query *query,
 	 */
@@ -2453,9 +2446,9 @@ query_tree_walker(Query *query,
 
@@ -2474,7 +2467,7 @@ query_tree_walker(Query *query,
 
 	if (!(flags & QTW_IGNORE_CTE_SUBQUERIES))
 	{
-		if (walker((Node *) query->cteList, context))
+		if (WALK(query->cteList))
 			return true;
 	}
 	if (!(flags & QTW_IGNORE_RANGE_TABLE))
@@ -2492,7 +2485,7 @@ query_tree_walker(Query *query,
  */
 bool
 range_table_walker(List *rtable,
-				   bool (*walker) (),
+				   tree_walker_callback walker,
 				   void *context,
 				   int flags)
 {
@@ -2513,7 +2506,7 @@ range_table_walker(List *rtable,
  */
 bool
 range_table_entry_walker(RangeTblEntry *rte,
-						 bool (*walker) (),
+						 tree_walker_callback walker,
 						 void *context,
 						 int flags)
 {
@@ -2523,35 +2516,35 @@ range_table_entry_walker(RangeTblEntry *rte,
 	 * specify neither flag, the walker won't be called on the RTE at all.
 	 */
 	if (flags & QTW_EXAMINE_RTES_BEFORE)
-		if (walker(rte, context))
+		if (WALK(rte))
 			return true;
 
 	switch (rte->rtekind)
 	{
 		case RTE_RELATION:
@@ -2561,11 +2554,11 @@ range_table_entry_walker(RangeTblEntry *rte,
 			break;
 	}

 
 	return false;
@@ -2580,7 +2573,7 @@ range_table_entry_walker(RangeTblEntry *rte,
  * (or appropriately modified substitute for) the subtree it is handed.
  * A mutator routine should look like this:
  *
- * Node * my_mutator (Node *node, my_struct *context)
+ * Node * my_mutator (Node *node, void *context)
  * {
  *		if (node == NULL)
  *			return NULL;
@@ -2594,7 +2587,7 @@ range_table_entry_walker(RangeTblEntry *rte,
  *			... do special transformations of other node types
  *		}
  *		// for any node type not specially processed, do:
- *		return expression_tree_mutator(node, my_mutator, (void *) context);
+ *		return expression_tree_mutator(node, my_mutator, context);
  * }
  *
  * The "context" argument points to a struct that holds whatever context
@@ -2636,7 +2629,7 @@ range_table_entry_walker(RangeTblEntry *rte,
 
 Node *
 expression_tree_mutator(Node *node,
-						Node *(*mutator) (),
+						tree_mutator_callback mutator,
 						void *context)
 {
 	/*
@@ -3367,7 +3360,7 @@ expression_tree_mutator(Node *node,
  */
 Query *
 query_tree_mutator(Query *query,
-				   Node *(*mutator) (),
+				   tree_mutator_callback mutator,
 				   void *context,
 				   int flags)
 {
@@ -3457,7 +3450,7 @@ query_tree_mutator(Query *query,
  */
 List *
 range_table_mutator(List *rtable,
-					Node *(*mutator) (),
+					tree_mutator_callback mutator,
 					void *context,
 					int flags)
 {
@@ -3526,7 +3519,7 @@ range_table_mutator(List *rtable,
  */
 bool
 query_or_expression_tree_walker(Node *node,
-								bool (*walker) (),
+								tree_walker_callback walker,
 								void *context,
 								int flags)
 {
@@ -3536,7 +3529,7 @@ query_or_expression_tree_walker(Node *node,
 								 context,
 								 flags);
 	else
-		return walker(node, context);
+		return WALK(node);
 }
 
 /*
@@ -3549,7 +3542,7 @@ query_or_expression_tree_walker(Node *node,
  */
 Node *
 query_or_expression_tree_mutator(Node *node,
-								 Node *(*mutator) (),
+								 tree_mutator_callback mutator,
 								 void *context,
 								 int flags)
 {
@@ -3580,7 +3573,7 @@ query_or_expression_tree_mutator(Node *node,
  */
 bool
 raw_expression_tree_walker(Node *node,
-						   bool (*walker) (),
+						   tree_walker_callback walker,
 						   void *context)
 {
 	ListCell   *temp;
@@ -3614,17 +3607,17 @@ raw_expression_tree_walker(Node *node,
 			/* we assume the colnames list isn't interesting */
 			break;
 		case T_RangeVar:
-			return walker(((RangeVar *) node)->alias, context);
+			return WALK(((RangeVar *) node)->alias);
 		case T_GroupingFunc:
-			return walker(((GroupingFunc *) node)->args, context);
+			return WALK(((GroupingFunc *) node)->args);
 		case T_SubLink:
 			{
 				SubLink    *sublink = (SubLink *) node;
 
@@ -3632,55 +3625,55 @@ raw_expression_tree_walker(Node *node,

 
 
@@ -3689,18 +3682,18 @@ raw_expression_tree_walker(Node *node,
 
@@ -3708,17 +3701,17 @@ raw_expression_tree_walker(Node *node,
 
@@ -3726,15 +3719,15 @@ raw_expression_tree_walker(Node *node,
 
@@ -3742,17 +3735,17 @@ raw_expression_tree_walker(Node *node,
 
@@ -3760,15 +3753,15 @@ raw_expression_tree_walker(Node *node,
 
@@ -3776,11 +3769,11 @@ raw_expression_tree_walker(Node *node,
 
@@ -3788,37 +3781,37 @@ raw_expression_tree_walker(Node *node,
 
@@ -3826,9 +3819,9 @@ raw_expression_tree_walker(Node *node,
 
@@ -3836,9 +3829,9 @@ raw_expression_tree_walker(Node *node,
 
@@ -3847,7 +3840,7 @@ raw_expression_tree_walker(Node *node,
 
-				if (walker(expr->args, context))
+				if (WALK(expr->args))
 					return true;
 			}
 			break;
@@ -3858,26 +3851,26 @@ raw_expression_tree_walker(Node *node,
 			{
 				FuncCall   *fcall = (FuncCall *) node;

@@ -3885,51 +3878,51 @@ raw_expression_tree_walker(Node *node,

 
 
@@ -3937,9 +3930,9 @@ raw_expression_tree_walker(Node *node,
 
@@ -3947,11 +3940,11 @@ raw_expression_tree_walker(Node *node,
 
@@ -3959,12 +3952,12 @@ raw_expression_tree_walker(Node *node,
 
@@ -3972,15 +3965,15 @@ raw_expression_tree_walker(Node *node,
 
@@ -3988,9 +3981,9 @@ raw_expression_tree_walker(Node *node,
 
@@ -3998,9 +3991,9 @@ raw_expression_tree_walker(Node *node,
 
@@ -4009,13 +4002,13 @@ raw_expression_tree_walker(Node *node,
 
@@ -4024,34 +4017,34 @@ raw_expression_tree_walker(Node *node,

 
@@ -4059,17 +4052,17 @@ raw_expression_tree_walker(Node *node,
 
@@ -4086,12 +4079,15 @@ raw_expression_tree_walker(Node *node,
+					  planstate_tree_walker_callback walker,
 
+	/* We don't need implicit coercions to Node here */
+#define PSWALK(n) walker(n, context)
+
 	/* Guard against stack overflow due to overly complex plan trees */
 	check_stack_depth();
 
@@ -4102,14 +4098,14 @@ planstate_tree_walker(PlanState *planstate,
 	/* lefttree */
 	if (outerPlanState(planstate))
 	{
-		if (walker(outerPlanState(planstate), context))
+		if (PSWALK(outerPlanState(planstate)))
 			return true;
 	}
 
 	/* righttree */
 	if (innerPlanState(planstate))
 	{
-		if (walker(innerPlanState(planstate), context))
+		if (PSWALK(innerPlanState(planstate)))
 			return true;
 	}
 
@@ -4141,13 +4137,13 @@ planstate_tree_walker(PlanState *planstate,
 				return true;
 			break;
 		case T_SubqueryScan:
-			if (walker(((SubqueryScanState *) planstate)->subplan, context))
+			if (PSWALK(((SubqueryScanState *) planstate)->subplan))
 				return true;
 			break;
 		case T_CustomScan:
 			foreach(lc, ((CustomScanState *) planstate)->custom_ps)
 			{
-				if (walker((PlanState *) lfirst(lc), context))
+				if (PSWALK(lfirst(lc)))
 					return true;
 			}
 			break;
@@ -4167,7 +4163,7 @@ planstate_tree_walker(PlanState *planstate,
  */
 static bool
 planstate_walk_subplans(List *plans,
-						bool (*walker) (),
+						planstate_tree_walker_callback walker,
 						void *context)
 {
 	ListCell   *lc;
@@ -4176,7 +4172,7 @@ planstate_walk_subplans(List *plans,
 	{
 		SubPlanState *sps = lfirst_node(SubPlanState, lc);
 
-		if (walker(sps->planstate, context))
+		if (PSWALK(sps->planstate))
 			return true;
 	}
 
@@ -4189,13 +4185,14 @@ planstate_walk_subplans(List *plans,
  */
 static bool
 planstate_walk_members(PlanState **planstates, int nplans,
-					   bool (*walker) (), void *context)
+					   planstate_tree_walker_callback walker,
+					   void *context)
 {
 	int			j;
 
 	for (j = 0; j < nplans; j++)
 	{
-		if (walker(planstates[j], context))
+		if (PSWALK(planstates[j]))
 			return true;
 	}
 
index f486d42441..1e0d43b183 100644
 
 static bool
-cost_qual_eval_walker(Node *node, cost_qual_eval_context *context)
+cost_qual_eval_walker(Node *node, void *ctx)
 {
+	cost_qual_eval_context *context = ctx;
+
 	if (node == NULL)
 		return false;
 
@@ -4986,8 +4988,7 @@ cost_qual_eval_walker(Node *node, cost_qual_eval_context *context)
 	}
 
 	/* recurse into children */
-	return expression_tree_walker(node, cost_qual_eval_walker,
-								  (void *) context);
+	return expression_tree_walker(node, cost_qual_eval_walker, ctx);
 }
 
 /*
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index cd8a3ef7cb..ed1f25d84b 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -162,7 +162,7 @@ static NestLoop *create_nestloop_plan(PlannerInfo *root, NestPath *best_path);
 static MergeJoin *create_mergejoin_plan(PlannerInfo *root, MergePath *best_path);
 static HashJoin *create_hashjoin_plan(PlannerInfo *root, HashPath *best_path);
 static Node *replace_nestloop_params(PlannerInfo *root, Node *expr);
-static Node *replace_nestloop_params_mutator(Node *node, PlannerInfo *root);
+static Node *replace_nestloop_params_mutator(Node *node, void *ctx);
 static void fix_indexqual_references(PlannerInfo *root, IndexPath *index_path,
 									 List **stripped_indexquals_p,
 									 List **fixed_indexquals_p);
@@ -4891,8 +4891,10 @@ replace_nestloop_params(PlannerInfo *root, Node *expr)
 }
 
 static Node *
-replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
+replace_nestloop_params_mutator(Node *node, void *ctx)
 {
+	PlannerInfo *root = ctx;
+
 	if (node == NULL)
 		return NULL;
 	if (IsA(node, Var))
@@ -4938,16 +4940,13 @@ replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
 
 			memcpy(newphv, phv, sizeof(PlaceHolderVar));
 			newphv->phexpr = (Expr *)
-				replace_nestloop_params_mutator((Node *) phv->phexpr,
-												root);
+				replace_nestloop_params_mutator((Node *) phv->phexpr, ctx);
 			return (Node *) newphv;
 		}
 		/* Replace the PlaceHolderVar with a nestloop Param */
 		return (Node *) replace_nestloop_param_placeholdervar(root, phv);
 	}
-	return expression_tree_mutator(node,
-								   replace_nestloop_params_mutator,
-								   (void *) root);
+	return expression_tree_mutator(node, replace_nestloop_params_mutator, ctx);
 }
 
 /*
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 1cb0abdbc1..228c15f6e6 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -113,7 +113,7 @@ typedef struct
 
 static void add_rtes_to_flat_rtable(PlannerInfo *root, bool recursing);
 static void flatten_unplanned_rtes(PlannerGlobal *glob, RangeTblEntry *rte);
-static bool flatten_rtes_walker(Node *node, PlannerGlobal *glob);
+static bool flatten_rtes_walker(Node *node, void *ctx);
 static void add_rte_to_flat_rtable(PlannerGlobal *glob, RangeTblEntry *rte);
 static Plan *set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset);
 static Plan *set_indexonlyscan_references(PlannerInfo *root,
@@ -139,8 +139,8 @@ static void set_hash_references(PlannerInfo *root, Plan *plan, int rtoffset);
 static Relids offset_relid_set(Relids relids, int rtoffset);
 static Node *fix_scan_expr(PlannerInfo *root, Node *node,
 						   int rtoffset, double num_exec);
-static Node *fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context);
-static bool fix_scan_expr_walker(Node *node, fix_scan_expr_context *context);
+static Node *fix_scan_expr_mutator(Node *node, void *ctx);
+static bool fix_scan_expr_walker(Node *node, void *ctx);
 static void set_join_references(PlannerInfo *root, Join *join, int rtoffset);
 static void set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset);
 static void set_param_references(PlannerInfo *root, Plan *plan);
@@ -164,15 +164,13 @@ static List *fix_join_expr(PlannerInfo *root,
 						   indexed_tlist *inner_itlist,
 						   Index acceptable_rel,
 						   int rtoffset, double num_exec);
-static Node *fix_join_expr_mutator(Node *node,
-								   fix_join_expr_context *context);
+static Node *fix_join_expr_mutator(Node *node, void *ctx);
 static Node *fix_upper_expr(PlannerInfo *root,
 							Node *node,
 							indexed_tlist *subplan_itlist,
 							int newvarno,
 							int rtoffset, double num_exec);
-static Node *fix_upper_expr_mutator(Node *node,
-									fix_upper_expr_context *context);
+static Node *fix_upper_expr_mutator(Node *node, void *ctx);
 static List *set_returning_clause_references(PlannerInfo *root,
 											 List *rlist,
 											 Plan *topplan,
@@ -453,8 +451,10 @@ flatten_unplanned_rtes(PlannerGlobal *glob, RangeTblEntry *rte)
 }
 
 static bool
-flatten_rtes_walker(Node *node, PlannerGlobal *glob)
+flatten_rtes_walker(Node *node, void *ctx)
 {
+	PlannerGlobal *glob = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, RangeTblEntry))
@@ -471,11 +471,10 @@ flatten_rtes_walker(Node *node, PlannerGlobal *glob)
 		/* Recurse into subselects */
 		return query_tree_walker((Query *) node,
 								 flatten_rtes_walker,
-								 (void *) glob,
+								 ctx,
 								 QTW_EXAMINE_RTES_BEFORE);
 	}
-	return expression_tree_walker(node, flatten_rtes_walker,
-								  (void *) glob);
+	return expression_tree_walker(node, flatten_rtes_walker, ctx);
 }
 
 /*
@@ -2055,8 +2054,10 @@ fix_scan_expr(PlannerInfo *root, Node *node, int rtoffset, double num_exec)
 }
 
 static Node *
-fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context)
+fix_scan_expr_mutator(Node *node, void *ctx)
 {
+	fix_scan_expr_context *context = ctx;
+
 	if (node == NULL)
 		return NULL;
 	if (IsA(node, Var))
@@ -2115,29 +2116,29 @@ fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context)
 		/* At scan level, we should always just evaluate the contained expr */
 		PlaceHolderVar *phv = (PlaceHolderVar *) node;
 
-		return fix_scan_expr_mutator((Node *) phv->phexpr, context);
+		return fix_scan_expr_mutator((Node *) phv->phexpr, ctx);
 	}
 	if (IsA(node, AlternativeSubPlan))
 		return fix_scan_expr_mutator(fix_alternative_subplan(context->root,
 															 (AlternativeSubPlan *) node,
 															 context->num_exec),
-									 context);
+									 ctx);
 	fix_expr_common(context->root, node);
-	return expression_tree_mutator(node, fix_scan_expr_mutator,
-								   (void *) context);
+	return expression_tree_mutator(node, fix_scan_expr_mutator, ctx);
 }
 
 static bool
-fix_scan_expr_walker(Node *node, fix_scan_expr_context *context)
+fix_scan_expr_walker(Node *node, void *ctx)
 {
+	fix_scan_expr_context *context = ctx;
+
 	if (node == NULL)
 		return false;
 	Assert(!(IsA(node, Var) && ((Var *) node)->varno == ROWID_VAR));
 	Assert(!IsA(node, PlaceHolderVar));
 	Assert(!IsA(node, AlternativeSubPlan));
 	fix_expr_common(context->root, node);
-	return expression_tree_walker(node, fix_scan_expr_walker,
-								  (void *) context);
+	return expression_tree_walker(node, fix_scan_expr_walker, ctx);
 }
 
 /*
@@ -2825,8 +2826,9 @@ fix_join_expr(PlannerInfo *root,
 }
 
 static Node *
-fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
+fix_join_expr_mutator(Node *node, void *ctx)
 {
+	fix_join_expr_context *context = ctx;
 	Var		   *newvar;
 
 	if (node == NULL)
@@ -2893,7 +2895,7 @@ fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
 		}
 
 		/* If not supplied by input plans, evaluate the contained expr */
-		return fix_join_expr_mutator((Node *) phv->phexpr, context);
+		return fix_join_expr_mutator((Node *) phv->phexpr, ctx);
 	}
 	/* Try matching more complex expressions too, if tlists have any */
 	if (context->outer_itlist && context->outer_itlist->has_non_vars)
@@ -2919,11 +2921,9 @@ fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
 		return fix_join_expr_mutator(fix_alternative_subplan(context->root,
 															 (AlternativeSubPlan *) node,
 															 context->num_exec),
-									 context);
+									 ctx);
 	fix_expr_common(context->root, node);
-	return expression_tree_mutator(node,
-								   fix_join_expr_mutator,
-								   (void *) context);
+	return expression_tree_mutator(node, fix_join_expr_mutator, ctx);
 }
 
 /*
@@ -2976,8 +2976,9 @@ fix_upper_expr(PlannerInfo *root,
 }
 
 static Node *
-fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
+fix_upper_expr_mutator(Node *node, void *ctx)
 {
+	fix_upper_expr_context *context = ctx;
 	Var		   *newvar;
 
 	if (node == NULL)
@@ -3008,7 +3009,7 @@ fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
 				return (Node *) newvar;
 		}
 		/* If not supplied by input plan, evaluate the contained expr */
-		return fix_upper_expr_mutator((Node *) phv->phexpr, context);
+		return fix_upper_expr_mutator((Node *) phv->phexpr, ctx);
 	}
 	/* Try matching more complex expressions too, if tlist has any */
 	if (context->subplan_itlist->has_non_vars)
@@ -3048,11 +3049,9 @@ fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
 		return fix_upper_expr_mutator(fix_alternative_subplan(context->root,
 															  (AlternativeSubPlan *) node,
 															  context->num_exec),
-									  context);
+									  ctx);
 	fix_expr_common(context->root, node);
-	return expression_tree_mutator(node,
-								   fix_upper_expr_mutator,
-								   (void *) context);
+	return expression_tree_mutator(node, fix_upper_expr_mutator, ctx);
 }
 
 /*
@@ -3127,9 +3126,10 @@ set_returning_clause_references(PlannerInfo *root,
  *		in the targetlist which references that WindowFunc.
  */
 static Node *
-fix_windowagg_condition_expr_mutator(Node *node,
-									 fix_windowagg_cond_context *context)
+fix_windowagg_condition_expr_mutator(Node *node, void *ctx)
 {
+	fix_windowagg_cond_context *context = ctx;
+
 	if (node == NULL)
 		return NULL;
 
@@ -3145,9 +3145,8 @@ fix_windowagg_condition_expr_mutator(Node *node,
 		elog(ERROR, "WindowFunc not found in subplan target lists");
 	}
 
-	return expression_tree_mutator(node,
-								   fix_windowagg_condition_expr_mutator,
-								   (void *) context);
+	return expression_tree_mutator(node, fix_windowagg_condition_expr_mutator,
+								   ctx);
 }
 
 /*
@@ -3323,8 +3322,10 @@ extract_query_dependencies(Node *query,
  * and invalItems lists are added to as needed.
  */
 bool
-extract_query_dependencies_walker(Node *node, PlannerInfo *context)
+extract_query_dependencies_walker(Node *node, void *ctx)
 {
+	PlannerInfo *context = ctx;
+
 	if (node == NULL)
 		return false;
 	Assert(!IsA(node, PlaceHolderVar));
@@ -3365,10 +3366,9 @@ extract_query_dependencies_walker(Node *node, PlannerInfo *context)
 
 		/* And recurse into the query's subexpressions */
 		return query_tree_walker(query, extract_query_dependencies_walker,
-								 (void *) context, 0);
+								 ctx, 0);
 	}
 	/* Extract function dependencies and check for regclass Consts */
 	fix_expr_common(context, node);
-	return expression_tree_walker(node, extract_query_dependencies_walker,
-								  (void *) context);
+	return expression_tree_walker(node, extract_query_dependencies_walker, ctx);
 }
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index 92e3338584..e2785b1fde 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -77,8 +77,7 @@ static List *generate_subquery_vars(PlannerInfo *root, List *tlist,
 static Node *convert_testexpr(PlannerInfo *root,
 							  Node *testexpr,
 							  List *subst_nodes);
-static Node *convert_testexpr_mutator(Node *node,
-									  convert_testexpr_context *context);
+static Node *convert_testexpr_mutator(Node *node, void *ctx);
 static bool subplan_is_hashable(Plan *plan);
 static bool subpath_is_hashable(Path *path);
 static bool testexpr_is_hashable(Node *testexpr, List *param_ids);
@@ -87,22 +86,21 @@ static bool hash_ok_operator(OpExpr *expr);
 static bool contain_dml(Node *node);
 static bool contain_dml_walker(Node *node, void *context);
 static bool contain_outer_selfref(Node *node);
-static bool contain_outer_selfref_walker(Node *node, Index *depth);
+static bool contain_outer_selfref_walker(Node *node, void *ctx);
 static void inline_cte(PlannerInfo *root, CommonTableExpr *cte);
-static bool inline_cte_walker(Node *node, inline_cte_walker_context *context);
+static bool inline_cte_walker(Node *node, void *ctx);
 static bool simplify_EXISTS_query(PlannerInfo *root, Query *query);
 static Query *convert_EXISTS_to_ANY(PlannerInfo *root, Query *subselect,
 									Node **testexpr, List **paramIds);
-static Node *replace_correlation_vars_mutator(Node *node, PlannerInfo *root);
-static Node *process_sublinks_mutator(Node *node,
-									  process_sublinks_context *context);
+static Node *replace_correlation_vars_mutator(Node *node, void *ctx);
+static Node *process_sublinks_mutator(Node *node, void *ctx);
 static Bitmapset *finalize_plan(PlannerInfo *root,
 								Plan *plan,
 								int gather_param,
 								Bitmapset *valid_params,
 								Bitmapset *scan_params);
-static bool finalize_primnode(Node *node, finalize_primnode_context *context);
-static bool finalize_agg_primnode(Node *node, finalize_primnode_context *context);
+static bool finalize_primnode(Node *node, void *ctx);
+static bool finalize_agg_primnode(Node *node, void *ctx);

 /*
@@ -664,9 +662,10 @@ convert_testexpr(PlannerInfo *root,
 }
 
 static Node *
-convert_testexpr_mutator(Node *node,
-						 convert_testexpr_context *context)
+convert_testexpr_mutator(Node *node, void *ctx)
 {
+	convert_testexpr_context *context = ctx;
+
 	if (node == NULL)
 		return NULL;
 	if (IsA(node, Param))
@@ -710,9 +709,7 @@ convert_testexpr_mutator(Node *node,
 		 */
 		return node;
 	}
-	return expression_tree_mutator(node,
-								   convert_testexpr_mutator,
-								   (void *) context);
+	return expression_tree_mutator(node, convert_testexpr_mutator, ctx);
 }
 
 /*
@@ -1108,8 +1105,10 @@ contain_outer_selfref(Node *node)
 }
 
 static bool
-contain_outer_selfref_walker(Node *node, Index *depth)
+contain_outer_selfref_walker(Node *node, void *ctx)
 {
+	Index	   *depth = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, RangeTblEntry))
@@ -1135,14 +1134,13 @@ contain_outer_selfref_walker(Node *node, Index *depth)
 		(*depth)++;
 
 		result = query_tree_walker(query, contain_outer_selfref_walker,
-								   (void *) depth, QTW_EXAMINE_RTES_BEFORE);
+								   ctx, QTW_EXAMINE_RTES_BEFORE);
 
 		(*depth)--;
 
 		return result;
 	}
-	return expression_tree_walker(node, contain_outer_selfref_walker,
-								  (void *) depth);
+	return expression_tree_walker(node, contain_outer_selfref_walker, ctx);
 }
 
 /*
@@ -1162,8 +1160,10 @@ inline_cte(PlannerInfo *root, CommonTableExpr *cte)
 }
 
 static bool
-inline_cte_walker(Node *node, inline_cte_walker_context *context)
+inline_cte_walker(Node *node, void *ctx)
 {
+	inline_cte_walker_context *context = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, Query))
@@ -1226,7 +1226,7 @@ inline_cte_walker(Node *node, inline_cte_walker_context *context)
 		return false;
 	}
 
-	return expression_tree_walker(node, inline_cte_walker, context);
+	return expression_tree_walker(node, inline_cte_walker, ctx);
 }

@@ -1871,8 +1871,10 @@ SS_replace_correlation_vars(PlannerInfo *root, Node *expr)
 }
 
 static Node *
-replace_correlation_vars_mutator(Node *node, PlannerInfo *root)
+replace_correlation_vars_mutator(Node *node, void *ctx)
 {
+	PlannerInfo *root = ctx;
+
 	if (node == NULL)
 		return NULL;
 	if (IsA(node, Var))
@@ -1896,9 +1898,7 @@ replace_correlation_vars_mutator(Node *node, PlannerInfo *root)
 		if (((GroupingFunc *) node)->agglevelsup > 0)
 			return (Node *) replace_outer_grouping(root, (GroupingFunc *) node);
 	}
-	return expression_tree_mutator(node,
-								   replace_correlation_vars_mutator,
-								   (void *) root);
+	return expression_tree_mutator(node, replace_correlation_vars_mutator, ctx);
 }
 
 /*
@@ -1919,8 +1919,9 @@ SS_process_sublinks(PlannerInfo *root, Node *expr, bool isQual)
 }
 
 static Node *
-process_sublinks_mutator(Node *node, process_sublinks_context *context)
+process_sublinks_mutator(Node *node, void *ctx)
 {
+	process_sublinks_context *context = ctx;
 	process_sublinks_context locContext;
 
 	locContext.root = context->root;
@@ -2837,8 +2838,10 @@ finalize_plan(PlannerInfo *root, Plan *plan,
  * expression tree to the result set.
  */
 static bool
-finalize_primnode(Node *node, finalize_primnode_context *context)
+finalize_primnode(Node *node, void *ctx)
 {
+	finalize_primnode_context *context = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, Param))
@@ -2892,8 +2895,7 @@ finalize_primnode(Node *node, finalize_primnode_context *context)
 
 		return false;			/* no more to do here */
 	}
-	return expression_tree_walker(node, finalize_primnode,
-								  (void *) context);
+	return expression_tree_walker(node, finalize_primnode, ctx);
 }
 
 /*
@@ -2902,8 +2904,10 @@ finalize_primnode(Node *node, finalize_primnode_context *context)
  * arguments to the result set.
  */
 static bool
-finalize_agg_primnode(Node *node, finalize_primnode_context *context)
+finalize_agg_primnode(Node *node, void *ctx)
 {
+	finalize_primnode_context *context = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, Aggref))
@@ -2915,8 +2919,7 @@ finalize_agg_primnode(Node *node, finalize_primnode_context *context)
 		finalize_primnode((Node *) agg->aggfilter, context);
 		return false;			/* there can't be any Aggrefs below here */
 	}
-	return expression_tree_walker(node, finalize_agg_primnode,
-								  (void *) context);
+	return expression_tree_walker(node, finalize_agg_primnode, ctx);
 }
 
 /*
diff --git a/src/backend/optimizer/prep/prepagg.c b/src/backend/optimizer/prep/prepagg.c
index da89b55402..d3fa4897a7 100644
--- a/src/backend/optimizer/prep/prepagg.c
+++ b/src/backend/optimizer/prep/prepagg.c
@@ -52,7 +52,7 @@
 #include "utils/memutils.h"
 #include "utils/syscache.h"
 
-static bool preprocess_aggrefs_walker(Node *node, PlannerInfo *root);
+static bool preprocess_aggrefs_walker(Node *node, void *ctx);
 static int	find_compatible_agg(PlannerInfo *root, Aggref *newagg,
 								List **same_input_transnos);
 static int	find_compatible_trans(PlannerInfo *root, Aggref *newagg,
@@ -322,8 +322,10 @@ preprocess_aggref(Aggref *aggref, PlannerInfo *root)
 }
 
 static bool
-preprocess_aggrefs_walker(Node *node, PlannerInfo *root)
+preprocess_aggrefs_walker(Node *node, void *ctx)
 {
+	PlannerInfo *root = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, Aggref))
@@ -340,8 +342,7 @@ preprocess_aggrefs_walker(Node *node, PlannerInfo *root)
 		return false;
 	}
 	Assert(!IsA(node, SubLink));
-	return expression_tree_walker(node, preprocess_aggrefs_walker,
-								  (void *) root);
+	return expression_tree_walker(node, preprocess_aggrefs_walker, ctx);
 }

diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index 41c7066d90..f6eb7eef25 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -3399,9 +3399,10 @@ typedef struct
 } find_dependent_phvs_context;
 
 static bool
-find_dependent_phvs_walker(Node *node,
-						   find_dependent_phvs_context *context)
+find_dependent_phvs_walker(Node *node, void *ctx)
 {
+	find_dependent_phvs_context *context = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, PlaceHolderVar))
@@ -3421,7 +3422,7 @@ find_dependent_phvs_walker(Node *node,
 		context->sublevels_up++;
 		result = query_tree_walker((Query *) node,
 								   find_dependent_phvs_walker,
-								   (void *) context, 0);
+								   ctx, 0);
 		context->sublevels_up--;
 		return result;
 	}
@@ -3431,8 +3432,7 @@ find_dependent_phvs_walker(Node *node,
 	Assert(!IsA(node, PlaceHolderInfo));
 	Assert(!IsA(node, MinMaxAggInfo));
 
-	return expression_tree_walker(node, find_dependent_phvs_walker,
-								  (void *) context);
+	return expression_tree_walker(node, find_dependent_phvs_walker, ctx);
 }
 
 static bool
@@ -3518,9 +3518,10 @@ typedef struct
 } substitute_phv_relids_context;
 
 static bool
-substitute_phv_relids_walker(Node *node,
-							 substitute_phv_relids_context *context)
+substitute_phv_relids_walker(Node *node, void *ctx)
 {
+	substitute_phv_relids_context *context = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, PlaceHolderVar))
@@ -3547,7 +3548,7 @@ substitute_phv_relids_walker(Node *node,
 		context->sublevels_up++;
 		result = query_tree_walker((Query *) node,
 								   substitute_phv_relids_walker,
-								   (void *) context, 0);
+								   ctx, 0);
 		context->sublevels_up--;
 		return result;
 	}
@@ -3557,8 +3558,7 @@ substitute_phv_relids_walker(Node *node,
 	Assert(!IsA(node, PlaceHolderInfo));
 	Assert(!IsA(node, MinMaxAggInfo));
 
-	return expression_tree_walker(node, substitute_phv_relids_walker,
-								  (void *) context);
+	return expression_tree_walker(node, substitute_phv_relids_walker, ctx);
 }
 
 static void
diff --git a/src/backend/optimizer/util/appendinfo.c b/src/backend/optimizer/util/appendinfo.c
index 62cccf9d87..923aafd1f2 100644
--- a/src/backend/optimizer/util/appendinfo.c
+++ b/src/backend/optimizer/util/appendinfo.c
@@ -38,8 +38,7 @@ static void make_inh_translation_list(Relation oldrelation,
 									  Relation newrelation,
 									  Index newvarno,
 									  AppendRelInfo *appinfo);
-static Node *adjust_appendrel_attrs_mutator(Node *node,
-											adjust_appendrel_attrs_context *context);
+static Node *adjust_appendrel_attrs_mutator(Node *node, void *ctx);

 /*
@@ -211,9 +210,9 @@ adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos,
 }
 
 static Node *
-adjust_appendrel_attrs_mutator(Node *node,
-							   adjust_appendrel_attrs_context *context)
+adjust_appendrel_attrs_mutator(Node *node, void *ctx)
 {
+	adjust_appendrel_attrs_context *context = ctx;
 	AppendRelInfo **appinfos = context->appinfos;
 	int			nappinfos = context->nappinfos;
 	int			cnt;
@@ -389,7 +388,7 @@ adjust_appendrel_attrs_mutator(Node *node,
 
 		phv = (PlaceHolderVar *) expression_tree_mutator(node,
 														 adjust_appendrel_attrs_mutator,
-														 (void *) context);
+														 ctx);
 		/* now fix PlaceHolderVar's relid sets */
 		if (phv->phlevelsup == 0)
 			phv->phrels = adjust_child_relids(phv->phrels, context->nappinfos,
@@ -417,11 +416,11 @@ adjust_appendrel_attrs_mutator(Node *node,
 
 		/* Recursively fix the clause itself */
 		newinfo->clause = (Expr *)
-			adjust_appendrel_attrs_mutator((Node *) oldinfo->clause, context);
+			adjust_appendrel_attrs_mutator((Node *) oldinfo->clause, ctx);
 
 		/* and the modified version, if an OR clause */
 		newinfo->orclause = (Expr *)
-			adjust_appendrel_attrs_mutator((Node *) oldinfo->orclause, context);
+			adjust_appendrel_attrs_mutator((Node *) oldinfo->orclause, ctx);
 
 		/* adjust relid sets too */
 		newinfo->clause_relids = adjust_child_relids(oldinfo->clause_relids,
@@ -473,8 +472,7 @@ adjust_appendrel_attrs_mutator(Node *node,
 	Assert(!IsA(node, RangeTblRef));
 	Assert(!IsA(node, JoinExpr));
 
-	return expression_tree_mutator(node, adjust_appendrel_attrs_mutator,
-								   (void *) context);
+	return expression_tree_mutator(node, adjust_appendrel_attrs_mutator, ctx);
 }
 
 /*
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index bf3a7cae60..91867e4e01 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -92,24 +92,22 @@ typedef struct
 } max_parallel_hazard_context;
 
 static bool contain_agg_clause_walker(Node *node, void *context);
-static bool find_window_functions_walker(Node *node, WindowFuncLists *lists);
+static bool find_window_functions_walker(Node *node, void *ctx);
 static bool contain_subplans_walker(Node *node, void *context);
 static bool contain_mutable_functions_walker(Node *node, void *context);
 static bool contain_volatile_functions_walker(Node *node, void *context);
 static bool contain_volatile_functions_not_nextval_walker(Node *node, void *context);
-static bool max_parallel_hazard_walker(Node *node,
-									   max_parallel_hazard_context *context);
+static bool max_parallel_hazard_walker(Node *node, void *ctx);
 static bool contain_nonstrict_functions_walker(Node *node, void *context);
-static bool contain_exec_param_walker(Node *node, List *param_ids);
+static bool contain_exec_param_walker(Node *node, void *ctx);
 static bool contain_context_dependent_node(Node *clause);
-static bool contain_context_dependent_node_walker(Node *node, int *flags);
+static bool contain_context_dependent_node_walker(Node *node, void *ctx);
 static bool contain_leaked_vars_walker(Node *node, void *context);
 static Relids find_nonnullable_rels_walker(Node *node, bool top_level);
 static List *find_nonnullable_vars_walker(Node *node, bool top_level);
 static bool is_strict_saop(ScalarArrayOpExpr *expr, bool falseOK);
 static bool convert_saop_to_hashed_saop_walker(Node *node, void *context);
-static Node *eval_const_expressions_mutator(Node *node,
-											eval_const_expressions_context *context);
+static Node *eval_const_expressions_mutator(Node *node, void *ctx);
 static bool contain_non_const_walker(Node *node, void *context);
 static bool ece_function_is_safe(Oid funcid,
 								 eval_const_expressions_context *context);
@@ -145,14 +143,12 @@ static Expr *inline_function(Oid funcid, Oid result_type, Oid result_collid,
 							 eval_const_expressions_context *context);
 static Node *substitute_actual_parameters(Node *expr, int nargs, List *args,
 										  int *usecounts);
-static Node *substitute_actual_parameters_mutator(Node *node,
-												  substitute_actual_parameters_context *context);
+static Node *substitute_actual_parameters_mutator(Node *node, void *ctx);
 static void sql_inline_error_callback(void *arg);
 static Query *substitute_actual_srf_parameters(Query *expr,
 											   int nargs, List *args);
-static Node *substitute_actual_srf_parameters_mutator(Node *node,
-													  substitute_actual_srf_parameters_context *context);
-static bool pull_paramids_walker(Node *node, Bitmapset **context);
+static Node *substitute_actual_srf_parameters_mutator(Node *node, void *ctx);
+static bool pull_paramids_walker(Node *node, void *ctx);

 /*****************************************************************************
@@ -235,8 +231,10 @@ find_window_functions(Node *clause, Index maxWinRef)
 }
 
 static bool
-find_window_functions_walker(Node *node, WindowFuncLists *lists)
+find_window_functions_walker(Node *node, void *ctx)
 {
+	WindowFuncLists *lists = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, WindowFunc))
@@ -264,8 +262,7 @@ find_window_functions_walker(Node *node, WindowFuncLists *lists)
 		return false;
 	}
 	Assert(!IsA(node, SubLink));
-	return expression_tree_walker(node, find_window_functions_walker,
-								  (void *) lists);
+	return expression_tree_walker(node, find_window_functions_walker, ctx);
 }

@@ -713,8 +710,10 @@ max_parallel_hazard_checker(Oid func_id, void *context)
 }
 
 static bool
-max_parallel_hazard_walker(Node *node, max_parallel_hazard_context *context)
+max_parallel_hazard_walker(Node *node, void *ctx)
 {
+	max_parallel_hazard_context *context = ctx;
+
 	if (node == NULL)
 		return false;
 
@@ -850,13 +849,11 @@ max_parallel_hazard_walker(Node *node, max_parallel_hazard_context *context)
 		/* Recurse into subselects */
 		return query_tree_walker(query,
 								 max_parallel_hazard_walker,
-								 context, 0);
+								 ctx, 0);
 	}
 
 	/* Recurse to check arguments */
-	return expression_tree_walker(node,
-								  max_parallel_hazard_walker,
-								  context);
+	return expression_tree_walker(node, max_parallel_hazard_walker, ctx);
 }

@@ -1027,8 +1024,10 @@ contain_exec_param(Node *clause, List *param_ids)
 }
 
 static bool
-contain_exec_param_walker(Node *node, List *param_ids)
+contain_exec_param_walker(Node *node, void *ctx)
 {
+	List	   *param_ids = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, Param))
@@ -1073,8 +1072,10 @@ contain_context_dependent_node(Node *clause)
 #define CCDN_CASETESTEXPR_OK	0x0001	/* CaseTestExpr okay here? */
 
 static bool
-contain_context_dependent_node_walker(Node *node, int *flags)
+contain_context_dependent_node_walker(Node *node, void *ctx)
 {
+	int		   *flags = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, CaseTestExpr))
@@ -1104,7 +1105,7 @@ contain_context_dependent_node_walker(Node *node, int *flags)
 			*flags |= CCDN_CASETESTEXPR_OK;
 			res = expression_tree_walker(node,
 										 contain_context_dependent_node_walker,
-										 (void *) flags);
+										 ctx);
 			*flags = save_flags;
 			return res;
 		}
@@ -1128,7 +1129,7 @@ contain_context_dependent_node_walker(Node *node, int *flags)
 		return res;
 	}
 	return expression_tree_walker(node, contain_context_dependent_node_walker,
-								  (void *) flags);
+								  ctx);
 }
 
 /*****************************************************************************
@@ -2278,9 +2279,10 @@ estimate_expression_value(PlannerInfo *root, Node *node)
  * Recursive guts of eval_const_expressions/estimate_expression_value
  */
 static Node *
-eval_const_expressions_mutator(Node *node,
-							   eval_const_expressions_context *context)
+eval_const_expressions_mutator(Node *node, void *ctx)
 {
+	eval_const_expressions_context *context = ctx;
+
 	if (node == NULL)
 		return NULL;
 	switch (nodeTag(node))
@@ -4731,9 +4733,10 @@ substitute_actual_parameters(Node *expr, int nargs, List *args,
 }
 
 static Node *
-substitute_actual_parameters_mutator(Node *node,
-									 substitute_actual_parameters_context *context)
+substitute_actual_parameters_mutator(Node *node, void *ctx)
 {
+	substitute_actual_parameters_context *context = ctx;
+
 	if (node == NULL)
 		return NULL;
 	if (IsA(node, Param))
@@ -4753,7 +4756,7 @@ substitute_actual_parameters_mutator(Node *node,
 		return list_nth(context->args, param->paramid - 1);
 	}
 	return expression_tree_mutator(node, substitute_actual_parameters_mutator,
-								   (void *) context);
+								   ctx);
 }
 
 /*
@@ -5177,9 +5180,9 @@ substitute_actual_srf_parameters(Query *expr, int nargs, List *args)
 }
 
 static Node *
-substitute_actual_srf_parameters_mutator(Node *node,
-										 substitute_actual_srf_parameters_context *context)
+substitute_actual_srf_parameters_mutator(Node *node, void *ctx)
 {
+	substitute_actual_srf_parameters_context *context = ctx;
 	Node	   *result;
 
 	if (node == NULL)
@@ -5189,7 +5192,7 @@ substitute_actual_srf_parameters_mutator(Node *node,
 		context->sublevels_up++;
 		result = (Node *) query_tree_mutator((Query *) node,
 											 substitute_actual_srf_parameters_mutator,
-											 (void *) context,
+											 ctx,
 											 0);
 		context->sublevels_up--;
 		return result;
@@ -5214,7 +5217,7 @@ substitute_actual_srf_parameters_mutator(Node *node,
 	}
 	return expression_tree_mutator(node,
 								   substitute_actual_srf_parameters_mutator,
-								   (void *) context);
+								   ctx);
 }
 
 /*
@@ -5232,8 +5235,10 @@ pull_paramids(Expr *expr)
 }
 
 static bool
-pull_paramids_walker(Node *node, Bitmapset **context)
+pull_paramids_walker(Node *node, void *ctx)
 {
+	Bitmapset **context = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, Param))
@@ -5243,6 +5248,5 @@ pull_paramids_walker(Node *node, Bitmapset **context)
 		*context = bms_add_member(*context, param->paramid);
 		return false;
 	}
-	return expression_tree_walker(node, pull_paramids_walker,
-								  (void *) context);
+	return expression_tree_walker(node, pull_paramids_walker, ctx);
 }
diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c
index 784a1af82d..6feb248f56 100644
--- a/src/backend/optimizer/util/tlist.c
+++ b/src/backend/optimizer/util/tlist.c
@@ -59,8 +59,7 @@ typedef struct
 	Index		current_sgref;	/* current subexpr's sortgroupref, or 0 */
 } split_pathtarget_context;
 
-static bool split_pathtarget_walker(Node *node,
-									split_pathtarget_context *context);
+static bool split_pathtarget_walker(Node *node, void *ctx);
 static void add_sp_item_to_pathtarget(PathTarget *target,
 									  split_pathtarget_item *item);
 static void add_sp_items_to_pathtarget(PathTarget *target, List *items);
@@ -1074,8 +1073,10 @@ split_pathtarget_at_srfs(PlannerInfo *root,
  * lists.  Duplicates will be gotten rid of later.
  */
 static bool
-split_pathtarget_walker(Node *node, split_pathtarget_context *context)
+split_pathtarget_walker(Node *node, void *ctx)
 {
+	split_pathtarget_context *context = ctx;
+
 	if (node == NULL)
 		return false;
 
@@ -1181,8 +1182,7 @@ split_pathtarget_walker(Node *node, split_pathtarget_context *context)
 	 * examine its inputs.
 	 */
 	context->current_sgref = 0; /* subexpressions are not sortgroup items */
-	return expression_tree_walker(node, split_pathtarget_walker,
-								  (void *) context);
+	return expression_tree_walker(node, split_pathtarget_walker, ctx);
 }
 
 /*
diff --git a/src/backend/optimizer/util/var.c b/src/backend/optimizer/util/var.c
index 7db86c39ef..e528e754fe 100644
--- a/src/backend/optimizer/util/var.c
+++ b/src/backend/optimizer/util/var.c
@@ -68,18 +68,14 @@ typedef struct
 	bool		inserted_sublink;	/* have we inserted a SubLink? */
 } flatten_join_alias_vars_context;
 
-static bool pull_varnos_walker(Node *node,
-							   pull_varnos_context *context);
-static bool pull_varattnos_walker(Node *node, pull_varattnos_context *context);
-static bool pull_vars_walker(Node *node, pull_vars_context *context);
+static bool pull_varnos_walker(Node *node, void *ctx);
+static bool pull_varattnos_walker(Node *node, void *ctx);
+static bool pull_vars_walker(Node *node, void *ctx);
 static bool contain_var_clause_walker(Node *node, void *context);
-static bool contain_vars_of_level_walker(Node *node, int *sublevels_up);
-static bool locate_var_of_level_walker(Node *node,
-									   locate_var_of_level_context *context);
-static bool pull_var_clause_walker(Node *node,
-								   pull_var_clause_context *context);
-static Node *flatten_join_alias_vars_mutator(Node *node,
-											 flatten_join_alias_vars_context *context);
+static bool contain_vars_of_level_walker(Node *node, void *ctx);
+static bool locate_var_of_level_walker(Node *node, void *ctx);
+static bool pull_var_clause_walker(Node *node, void *ctx);
+static Node *flatten_join_alias_vars_mutator(Node *node, void *ctx);
 static Relids alias_relid_set(Query *query, Relids relids);

@@ -144,8 +140,10 @@ pull_varnos_of_level(PlannerInfo *root, Node *node, int levelsup)
 }
 
 static bool
-pull_varnos_walker(Node *node, pull_varnos_context *context)
+pull_varnos_walker(Node *node, void *ctx)
 {
+	pull_varnos_context *context = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, Var))
@@ -254,12 +252,11 @@ pull_varnos_walker(Node *node, pull_varnos_context *context)
 
 		context->sublevels_up++;
 		result = query_tree_walker((Query *) node, pull_varnos_walker,
-								   (void *) context, 0);
+								   ctx, 0);
 		context->sublevels_up--;
 		return result;
 	}
-	return expression_tree_walker(node, pull_varnos_walker,
-								  (void *) context);
+	return expression_tree_walker(node, pull_varnos_walker, ctx);
 }

@@ -291,8 +288,10 @@ pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
 }
 
 static bool
-pull_varattnos_walker(Node *node, pull_varattnos_context *context)
+pull_varattnos_walker(Node *node, void *ctx)
 {
+	pull_varattnos_context *context = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, Var))
@@ -309,8 +308,7 @@ pull_varattnos_walker(Node *node, pull_varattnos_context *context)
 	/* Should not find an unplanned subquery */
 	Assert(!IsA(node, Query));
 
-	return expression_tree_walker(node, pull_varattnos_walker,
-								  (void *) context);
+	return expression_tree_walker(node, pull_varattnos_walker, ctx);
 }

@@ -342,8 +340,10 @@ pull_vars_of_level(Node *node, int levelsup)
 }
 
 static bool
-pull_vars_walker(Node *node, pull_vars_context *context)
+pull_vars_walker(Node *node, void *ctx)
 {
+	pull_vars_context *context = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, Var))
@@ -370,12 +370,11 @@ pull_vars_walker(Node *node, pull_vars_context *context)
 
 		context->sublevels_up++;
 		result = query_tree_walker((Query *) node, pull_vars_walker,
-								   (void *) context, 0);
+								   ctx, 0);
 		context->sublevels_up--;
 		return result;
 	}
-	return expression_tree_walker(node, pull_vars_walker,
-								  (void *) context);
+	return expression_tree_walker(node, pull_vars_walker, ctx);
 }

@@ -439,8 +438,10 @@ contain_vars_of_level(Node *node, int levelsup)
 }
 
 static bool
-contain_vars_of_level_walker(Node *node, int *sublevels_up)
+contain_vars_of_level_walker(Node *node, void *ctx)
 {
+	int		   *sublevels_up = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, Var))
@@ -469,14 +470,12 @@ contain_vars_of_level_walker(Node *node, int *sublevels_up)
 		(*sublevels_up)++;
 		result = query_tree_walker((Query *) node,
 								   contain_vars_of_level_walker,
-								   (void *) sublevels_up,
+								   ctx,
 								   0);
 		(*sublevels_up)--;
 		return result;
 	}
-	return expression_tree_walker(node,
-								  contain_vars_of_level_walker,
-								  (void *) sublevels_up);
+	return expression_tree_walker(node, contain_vars_of_level_walker, ctx);
 }

@@ -512,9 +511,10 @@ locate_var_of_level(Node *node, int levelsup)
 }
 
 static bool
-locate_var_of_level_walker(Node *node,
-						   locate_var_of_level_context *context)
+locate_var_of_level_walker(Node *node, void *ctx)
 {
+	locate_var_of_level_context *context = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, Var))
@@ -543,14 +543,12 @@ locate_var_of_level_walker(Node *node,
 		context->sublevels_up++;
 		result = query_tree_walker((Query *) node,
 								   locate_var_of_level_walker,
-								   (void *) context,
+								   ctx,
 								   0);
 		context->sublevels_up--;
 		return result;
 	}
-	return expression_tree_walker(node,
-								  locate_var_of_level_walker,
-								  (void *) context);
+	return expression_tree_walker(node, locate_var_of_level_walker, ctx);
 }

@@ -614,8 +612,10 @@ pull_var_clause(Node *node, int flags)
 }
 
 static bool
-pull_var_clause_walker(Node *node, pull_var_clause_context *context)
+pull_var_clause_walker(Node *node, void *ctx)
 {
+	pull_var_clause_context *context = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, Var))
@@ -692,8 +692,7 @@ pull_var_clause_walker(Node *node, pull_var_clause_context *context)
 		else
 			elog(ERROR, "PlaceHolderVar found where not expected");
 	}
-	return expression_tree_walker(node, pull_var_clause_walker,
-								  (void *) context);
+	return expression_tree_walker(node, pull_var_clause_walker, ctx);
 }

@@ -738,9 +737,10 @@ flatten_join_alias_vars(Query *query, Node *node)
 }
 
 static Node *
-flatten_join_alias_vars_mutator(Node *node,
-								flatten_join_alias_vars_context *context)
+flatten_join_alias_vars_mutator(Node *node, void *ctx)
 {
+	flatten_join_alias_vars_context *context = ctx;
+
 	if (node == NULL)
 		return NULL;
 	if (IsA(node, Var))
@@ -868,8 +868,7 @@ flatten_join_alias_vars_mutator(Node *node,
 	Assert(!IsA(node, PlaceHolderInfo));
 	Assert(!IsA(node, MinMaxAggInfo));
 
-	return expression_tree_mutator(node, flatten_join_alias_vars_mutator,
-								   (void *) context);
+	return expression_tree_mutator(node, flatten_join_alias_vars_mutator, ctx);
 }
 
 /*
diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c
index 3ef9e8ee5e..1a40a5d7f2 100644
--- a/src/backend/parser/parse_agg.c
+++ b/src/backend/parser/parse_agg.c
@@ -55,19 +55,16 @@ static int	check_agg_arguments(ParseState *pstate,
 								List *directargs,
 								List *args,
 								Expr *filter);
-static bool check_agg_arguments_walker(Node *node,
-									   check_agg_arguments_context *context);
+static bool check_agg_arguments_walker(Node *node, void *ctx);
 static void check_ungrouped_columns(Node *node, ParseState *pstate, Query *qry,
 									List *groupClauses, List *groupClauseCommonVars,
 									bool have_non_var_grouping,
 									List **func_grouped_rels);
-static bool check_ungrouped_columns_walker(Node *node,
-										   check_ungrouped_columns_context *context);
+static bool check_ungrouped_columns_walker(Node *node, void *ctx);
 static void finalize_grouping_exprs(Node *node, ParseState *pstate, Query *qry,
 									List *groupClauses, bool hasJoinRTEs,
 									bool have_non_var_grouping);
-static bool finalize_grouping_exprs_walker(Node *node,
-										   check_ungrouped_columns_context *context);
+static bool finalize_grouping_exprs_walker(Node *node, void *ctx);
 static void check_agglevels_and_constraints(ParseState *pstate, Node *expr);
 static List *expand_groupingset_node(GroupingSet *gs);
 static Node *make_agg_arg(Oid argtype, Oid argcollation);
@@ -702,9 +699,10 @@ check_agg_arguments(ParseState *pstate,
 }
 
 static bool
-check_agg_arguments_walker(Node *node,
-						   check_agg_arguments_context *context)
+check_agg_arguments_walker(Node *node, void *ctx)
 {
+	check_agg_arguments_context *context = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, Var))
@@ -783,15 +781,13 @@ check_agg_arguments_walker(Node *node,
 		context->sublevels_up++;
 		result = query_tree_walker((Query *) node,
 								   check_agg_arguments_walker,
-								   (void *) context,
+								   ctx,
 								   0);
 		context->sublevels_up--;
 		return result;
 	}
 
-	return expression_tree_walker(node,
-								  check_agg_arguments_walker,
-								  (void *) context);
+	return expression_tree_walker(node, check_agg_arguments_walker, ctx);
 }
 
 /*
@@ -1276,9 +1272,9 @@ check_ungrouped_columns(Node *node, ParseState *pstate, Query *qry,
 }
 
 static bool
-check_ungrouped_columns_walker(Node *node,
-							   check_ungrouped_columns_context *context)
+check_ungrouped_columns_walker(Node *node, void *ctx)
 {
+	check_ungrouped_columns_context *context = ctx;
 	ListCell   *gl;
 
 	if (node == NULL)
@@ -1443,13 +1439,13 @@ check_ungrouped_columns_walker(Node *node,
 		context->sublevels_up++;
 		result = query_tree_walker((Query *) node,
 								   check_ungrouped_columns_walker,
-								   (void *) context,
+								   ctx,
 								   0);
 		context->sublevels_up--;
 		return result;
 	}
-	return expression_tree_walker(node, check_ungrouped_columns_walker,
-								  (void *) context);
+
+	return expression_tree_walker(node, check_ungrouped_columns_walker, ctx);
 }
 
 /*
@@ -1483,9 +1479,9 @@ finalize_grouping_exprs(Node *node, ParseState *pstate, Query *qry,
 }
 
 static bool
-finalize_grouping_exprs_walker(Node *node,
-							   check_ungrouped_columns_context *context)
+finalize_grouping_exprs_walker(Node *node, void *ctx)
 {
+	check_ungrouped_columns_context *context = ctx;
 	ListCell   *gl;
 
 	if (node == NULL)
@@ -1616,13 +1612,13 @@ finalize_grouping_exprs_walker(Node *node,
 		context->sublevels_up++;
 		result = query_tree_walker((Query *) node,
 								   finalize_grouping_exprs_walker,
-								   (void *) context,
+								   ctx,
 								   0);
 		context->sublevels_up--;
 		return result;
 	}
-	return expression_tree_walker(node, finalize_grouping_exprs_walker,
-								  (void *) context);
+
+	return expression_tree_walker(node, finalize_grouping_exprs_walker, ctx);
 }

diff --git a/src/backend/parser/parse_collate.c b/src/backend/parser/parse_collate.c
index 7582faabb3..921caa9de6 100644
--- a/src/backend/parser/parse_collate.c
+++ b/src/backend/parser/parse_collate.c
@@ -72,9 +72,8 @@ typedef struct
 	int			location2;		/* location of expr that set collation2 */
 } assign_collations_context;
 
-static bool assign_query_collations_walker(Node *node, ParseState *pstate);
-static bool assign_collations_walker(Node *node,
-									 assign_collations_context *context);
+static bool assign_query_collations_walker(Node *node, void *ctx);
+static bool assign_collations_walker(Node *node, void *ctx);
 static void merge_collation_state(Oid collation,
 								  CollateStrength strength,
 								  int location,
@@ -123,8 +122,10 @@ assign_query_collations(ParseState *pstate, Query *query)
  * have different collations.
  */
 static bool
-assign_query_collations_walker(Node *node, ParseState *pstate)
+assign_query_collations_walker(Node *node, void *ctx)
 {
+	ParseState *pstate = ctx;
+
 	/* Need do nothing for empty subexpressions */
 	if (node == NULL)
 		return false;
@@ -252,8 +253,9 @@ select_common_collation(ParseState *pstate, List *exprs, bool none_ok)
  * error if there are conflicting explicit collations for different members.
  */
 static bool
-assign_collations_walker(Node *node, assign_collations_context *context)
+assign_collations_walker(Node *node, void *ctx)
 {
+	assign_collations_context *context = ctx;
 	assign_collations_context loccontext;
 	Oid			collation;
 	CollateStrength strength;
diff --git a/src/backend/parser/parse_cte.c b/src/backend/parser/parse_cte.c
index 8fc8658608..5f43ccef1b 100644
--- a/src/backend/parser/parse_cte.c
+++ b/src/backend/parser/parse_cte.c
@@ -87,12 +87,12 @@ static void analyzeCTE(ParseState *pstate, CommonTableExpr *cte);
 
 /* Dependency processing functions */
 static void makeDependencyGraph(CteState *cstate);
-static bool makeDependencyGraphWalker(Node *node, CteState *cstate);
+static bool makeDependencyGraphWalker(Node *node, void *ctx);
 static void TopologicalSort(ParseState *pstate, CteItem *items, int numitems);
 
 /* Recursion validity checker functions */
 static void checkWellFormedRecursion(CteState *cstate);
-static bool checkWellFormedRecursionWalker(Node *node, CteState *cstate);
+static bool checkWellFormedRecursionWalker(Node *node, void *ctx);
 static void checkWellFormedSelectStmt(SelectStmt *stmt, CteState *cstate);

@@ -648,8 +648,10 @@ makeDependencyGraph(CteState *cstate)
  * CTEs in a WITH RECURSIVE list.
  */
 static bool
-makeDependencyGraphWalker(Node *node, CteState *cstate)
+makeDependencyGraphWalker(Node *node, void *ctx)
 {
+	CteState   *cstate = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, RangeVar))
@@ -767,9 +769,7 @@ makeDependencyGraphWalker(Node *node, CteState *cstate)
 		 */
 		return false;
 	}
-	return raw_expression_tree_walker(node,
-									  makeDependencyGraphWalker,
-									  (void *) cstate);
+	return raw_expression_tree_walker(node, makeDependencyGraphWalker, ctx);
 }
 
 /*
@@ -927,8 +927,9 @@ checkWellFormedRecursion(CteState *cstate)
  * Tree walker function to detect invalid self-references in a recursive query.
  */
 static bool
-checkWellFormedRecursionWalker(Node *node, CteState *cstate)
+checkWellFormedRecursionWalker(Node *node, void *ctx)
 {
+	CteState   *cstate = ctx;
 	RecursionContext save_context = cstate->context;
 
 	if (node == NULL)
@@ -1097,9 +1098,7 @@ checkWellFormedRecursionWalker(Node *node, CteState *cstate)
 		checkWellFormedRecursionWalker(sl->testexpr, cstate);
 		return false;
 	}
-	return raw_expression_tree_walker(node,
-									  checkWellFormedRecursionWalker,
-									  (void *) cstate);
+	return raw_expression_tree_walker(node, checkWellFormedRecursionWalker, ctx);
 }
 
 /*
diff --git a/src/backend/parser/parse_param.c b/src/backend/parser/parse_param.c
index f668abfcb3..536357326f 100644
--- a/src/backend/parser/parse_param.c
+++ b/src/backend/parser/parse_param.c
@@ -56,7 +56,7 @@ static Node *variable_paramref_hook(ParseState *pstate, ParamRef *pref);
 static Node *variable_coerce_param_hook(ParseState *pstate, Param *param,
 										Oid targetTypeId, int32 targetTypeMod,
 										int location);
-static bool check_parameter_resolution_walker(Node *node, ParseState *pstate);
+static bool check_parameter_resolution_walker(Node *node, void *ctx);
 static bool query_contains_extern_params_walker(Node *node, void *context);

@@ -287,8 +287,10 @@ check_variable_parameters(ParseState *pstate, Query *query)
  * and yet other instances seen later might have gotten coerced.
  */
 static bool
-check_parameter_resolution_walker(Node *node, ParseState *pstate)
+check_parameter_resolution_walker(Node *node, void *ctx)
 {
+	ParseState *pstate = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, Param))
@@ -321,10 +323,9 @@ check_parameter_resolution_walker(Node *node, ParseState *pstate)
 		/* Recurse into RTE subquery or not-yet-planned sublink subquery */
 		return query_tree_walker((Query *) node,
 								 check_parameter_resolution_walker,
-								 (void *) pstate, 0);
+								 ctx, 0);
 	}
-	return expression_tree_walker(node, check_parameter_resolution_walker,
-								  (void *) pstate);
+	return expression_tree_walker(node, check_parameter_resolution_walker, ctx);
 }
 
 /*
diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c
index 5ab4612367..fd5609e740 100644
--- a/src/backend/partitioning/partprune.c
+++ b/src/backend/partitioning/partprune.c
@@ -191,7 +191,7 @@ static PruneStepResult *get_matching_range_bounds(PartitionPruneContext *context
 												  StrategyNumber opstrategy, Datum *values, int nvalues,
 												  FmgrInfo *partsupfunc, Bitmapset *nullkeys);
 static Bitmapset *pull_exec_paramids(Expr *expr);
-static bool pull_exec_paramids_walker(Node *node, Bitmapset **context);
+static bool pull_exec_paramids_walker(Node *node, void *ctx);
 static Bitmapset *get_partkey_exec_paramids(List *steps);
 static PruneStepResult *perform_pruning_base_step(PartitionPruneContext *context,
 												  PartitionPruneStepOp *opstep);
@@ -3274,8 +3274,10 @@ pull_exec_paramids(Expr *expr)
 }
 
 static bool
-pull_exec_paramids_walker(Node *node, Bitmapset **context)
+pull_exec_paramids_walker(Node *node, void *ctx)
 {
+	Bitmapset **context = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, Param))
@@ -3286,8 +3288,7 @@ pull_exec_paramids_walker(Node *node, Bitmapset **context)
 			*context = bms_add_member(*context, param->paramid);
 		return false;
 	}
-	return expression_tree_walker(node, pull_exec_paramids_walker,
-								  (void *) context);
+	return expression_tree_walker(node, pull_exec_paramids_walker, ctx);
 }
 
 /*
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index 213eabfbb9..244aae8048 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -46,7 +46,7 @@
 
 static void checkRuleResultList(List *targetList, TupleDesc resultDesc,
 								bool isSelect, bool requireColumnNameMatch);
-static bool setRuleCheckAsUser_walker(Node *node, Oid *context);
+static bool setRuleCheckAsUser_walker(Node *node, void *ctx);
 static void setRuleCheckAsUser_Query(Query *qry, Oid userid);

@@ -801,8 +801,10 @@ setRuleCheckAsUser(Node *node, Oid userid)
 }
 
 static bool
-setRuleCheckAsUser_walker(Node *node, Oid *context)
+setRuleCheckAsUser_walker(Node *node, void *ctx)
 {
+	Oid		   *context = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, Query))
@@ -810,8 +812,7 @@ setRuleCheckAsUser_walker(Node *node, Oid *context)
 		setRuleCheckAsUser_Query((Query *) node, *context);
 		return false;
 	}
-	return expression_tree_walker(node, setRuleCheckAsUser_walker,
-								  (void *) context);
+	return expression_tree_walker(node, setRuleCheckAsUser_walker, ctx);
 }
 
 static void
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index d02fd83c0a..3294e31141 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -57,8 +57,7 @@ typedef struct acquireLocksOnSubLinks_context
 	bool		for_execute;	/* AcquireRewriteLocks' forExecute param */
 } acquireLocksOnSubLinks_context;
 
-static bool acquireLocksOnSubLinks(Node *node,
-								   acquireLocksOnSubLinks_context *context);
+static bool acquireLocksOnSubLinks(Node *node, void *ctx);
 static Query *rewriteRuleAction(Query *parsetree,
 								Query *rule_action,
 								Node *rule_qual,
@@ -298,8 +297,10 @@ AcquireRewriteLocks(Query *parsetree,
  * Walker to find sublink subqueries for AcquireRewriteLocks
  */
 static bool
-acquireLocksOnSubLinks(Node *node, acquireLocksOnSubLinks_context *context)
+acquireLocksOnSubLinks(Node *node, void *ctx)
 {
+	acquireLocksOnSubLinks_context *context = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, SubLink))
@@ -317,7 +318,7 @@ acquireLocksOnSubLinks(Node *node, acquireLocksOnSubLinks_context *context)
 	 * Do NOT recurse into Query nodes, because AcquireRewriteLocks already
 	 * processed subselects of subselects for us.
 	 */
-	return expression_tree_walker(node, acquireLocksOnSubLinks, context);
+	return expression_tree_walker(node, acquireLocksOnSubLinks, ctx);
 }

@@ -1944,8 +1945,10 @@ markQueryForLocking(Query *qry, Node *jtnode,
  * the SubLink's subselect link with the possibly-rewritten subquery.
  */
 static bool
-fireRIRonSubLink(Node *node, List *activeRIRs)
+fireRIRonSubLink(Node *node, void *ctx)
 {
+	List	   *activeRIRs = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, SubLink))
@@ -1962,8 +1965,7 @@ fireRIRonSubLink(Node *node, List *activeRIRs)
 	 * Do NOT recurse into Query nodes, because fireRIRrules already processed
 	 * subselects of subselects for us.
 	 */
-	return expression_tree_walker(node, fireRIRonSubLink,
-								  (void *) activeRIRs);
+	return expression_tree_walker(node, fireRIRonSubLink, ctx);
 }

diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c
index 101c39553a..2e449c4c3b 100644
--- a/src/backend/rewrite/rewriteManip.c
+++ b/src/backend/rewrite/rewriteManip.c
@@ -40,13 +40,10 @@ typedef struct
 	int			win_location;
 } locate_windowfunc_context;
 
-static bool contain_aggs_of_level_walker(Node *node,
-										 contain_aggs_of_level_context *context);
-static bool locate_agg_of_level_walker(Node *node,
-									   locate_agg_of_level_context *context);
+static bool contain_aggs_of_level_walker(Node *node, void *ctx);
+static bool locate_agg_of_level_walker(Node *node, void *ctx);
 static bool contain_windowfuncs_walker(Node *node, void *context);
-static bool locate_windowfunc_walker(Node *node,
-									 locate_windowfunc_context *context);
+static bool locate_windowfunc_walker(Node *node, void *ctx);
 static bool checkExprHasSubLink_walker(Node *node, void *context);
 static Relids offset_relid_set(Relids relids, int offset);
 static Relids adjust_relid_set(Relids relids, int oldrelid, int newrelid);
@@ -81,9 +78,10 @@ contain_aggs_of_level(Node *node, int levelsup)
 }
 
 static bool
-contain_aggs_of_level_walker(Node *node,
-							 contain_aggs_of_level_context *context)
+contain_aggs_of_level_walker(Node *node, void *ctx)
 {
+	contain_aggs_of_level_context *context = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, Aggref))
@@ -106,12 +104,11 @@ contain_aggs_of_level_walker(Node *node,
 		context->sublevels_up++;
 		result = query_tree_walker((Query *) node,
 								   contain_aggs_of_level_walker,
-								   (void *) context, 0);
+								   ctx, 0);
 		context->sublevels_up--;
 		return result;
 	}
-	return expression_tree_walker(node, contain_aggs_of_level_walker,
-								  (void *) context);
+	return expression_tree_walker(node, contain_aggs_of_level_walker, ctx);
 }
 
 /*
@@ -148,9 +145,10 @@ locate_agg_of_level(Node *node, int levelsup)
 }
 
 static bool
-locate_agg_of_level_walker(Node *node,
-						   locate_agg_of_level_context *context)
+locate_agg_of_level_walker(Node *node, void *ctx)
 {
+	locate_agg_of_level_context *context = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, Aggref))
@@ -180,12 +178,11 @@ locate_agg_of_level_walker(Node *node,
 		context->sublevels_up++;
 		result = query_tree_walker((Query *) node,
 								   locate_agg_of_level_walker,
-								   (void *) context, 0);
+								   ctx, 0);
 		context->sublevels_up--;
 		return result;
 	}
-	return expression_tree_walker(node, locate_agg_of_level_walker,
-								  (void *) context);
+	return expression_tree_walker(node, locate_agg_of_level_walker, ctx);
 }
 
 /*
@@ -251,8 +248,10 @@ locate_windowfunc(Node *node)
 }
 
 static bool
-locate_windowfunc_walker(Node *node, locate_windowfunc_context *context)
+locate_windowfunc_walker(Node *node, void *ctx)
 {
+	locate_windowfunc_context *context = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, WindowFunc))
@@ -265,8 +264,7 @@ locate_windowfunc_walker(Node *node, locate_windowfunc_context *context)
 		/* else fall through to examine argument */
 	}
 	/* Mustn't recurse into subselects */
-	return expression_tree_walker(node, locate_windowfunc_walker,
-								  (void *) context);
+	return expression_tree_walker(node, locate_windowfunc_walker, ctx);
 }
 
 /*
@@ -337,8 +335,10 @@ typedef struct
 } OffsetVarNodes_context;
 
 static bool
-OffsetVarNodes_walker(Node *node, OffsetVarNodes_context *context)
+OffsetVarNodes_walker(Node *node, void *ctx)
 {
+	OffsetVarNodes_context *context = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, Var))
@@ -413,12 +413,11 @@ OffsetVarNodes_walker(Node *node, OffsetVarNodes_context *context)
 
 		context->sublevels_up++;
 		result = query_tree_walker((Query *) node, OffsetVarNodes_walker,
-								   (void *) context, 0);
+								   ctx, 0);
 		context->sublevels_up--;
 		return result;
 	}
-	return expression_tree_walker(node, OffsetVarNodes_walker,
-								  (void *) context);
+	return expression_tree_walker(node, OffsetVarNodes_walker, ctx);
 }
 
 void
@@ -502,8 +501,10 @@ typedef struct
 } ChangeVarNodes_context;
 
 static bool
-ChangeVarNodes_walker(Node *node, ChangeVarNodes_context *context)
+ChangeVarNodes_walker(Node *node, void *ctx)
 {
+	ChangeVarNodes_context *context = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, Var))
@@ -598,12 +599,11 @@ ChangeVarNodes_walker(Node *node, ChangeVarNodes_context *context)
 
 		context->sublevels_up++;
 		result = query_tree_walker((Query *) node, ChangeVarNodes_walker,
-								   (void *) context, 0);
+								   ctx, 0);
 		context->sublevels_up--;
 		return result;
 	}
-	return expression_tree_walker(node, ChangeVarNodes_walker,
-								  (void *) context);
+	return expression_tree_walker(node, ChangeVarNodes_walker, ctx);
 }
 
 void
@@ -700,9 +700,10 @@ typedef struct
 } IncrementVarSublevelsUp_context;
 
 static bool
-IncrementVarSublevelsUp_walker(Node *node,
-							   IncrementVarSublevelsUp_context *context)
+IncrementVarSublevelsUp_walker(Node *node, void *ctx)
 {
+	IncrementVarSublevelsUp_context *context = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, Var))
@@ -763,13 +764,12 @@ IncrementVarSublevelsUp_walker(Node *node,
 		context->min_sublevels_up++;
 		result = query_tree_walker((Query *) node,
 								   IncrementVarSublevelsUp_walker,
-								   (void *) context,
+								   ctx,
 								   QTW_EXAMINE_RTES_BEFORE);
 		context->min_sublevels_up--;
 		return result;
 	}
-	return expression_tree_walker(node, IncrementVarSublevelsUp_walker,
-								  (void *) context);
+	return expression_tree_walker(node, IncrementVarSublevelsUp_walker, ctx);
 }
 
 void
@@ -823,9 +823,10 @@ typedef struct
 } rangeTableEntry_used_context;
 
 static bool
-rangeTableEntry_used_walker(Node *node,
-							rangeTableEntry_used_context *context)
+rangeTableEntry_used_walker(Node *node, void *ctx)
 {
+	rangeTableEntry_used_context *context = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, Var))
@@ -880,12 +881,11 @@ rangeTableEntry_used_walker(Node *node,
 
 		context->sublevels_up++;
 		result = query_tree_walker((Query *) node, rangeTableEntry_used_walker,
-								   (void *) context, 0);
+								   ctx, 0);
 		context->sublevels_up--;
 		return result;
 	}
-	return expression_tree_walker(node, rangeTableEntry_used_walker,
-								  (void *) context);
+	return expression_tree_walker(node, rangeTableEntry_used_walker, ctx);
 }
 
 bool
@@ -1131,9 +1131,10 @@ replace_rte_variables(Node *node, int target_varno, int sublevels_up,
 }
 
 Node *
-replace_rte_variables_mutator(Node *node,
-							  replace_rte_variables_context *context)
+replace_rte_variables_mutator(Node *node, void *ctx)
 {
+	replace_rte_variables_context *context = ctx;
+
 	if (node == NULL)
 		return NULL;
 	if (IsA(node, Var))
@@ -1184,15 +1185,14 @@ replace_rte_variables_mutator(Node *node,
 		context->inserted_sublink = ((Query *) node)->hasSubLinks;
 		newnode = query_tree_mutator((Query *) node,
 									 replace_rte_variables_mutator,
-									 (void *) context,
+									 ctx,
 									 0);
 		newnode->hasSubLinks |= context->inserted_sublink;
 		context->inserted_sublink = save_inserted_sublink;
 		context->sublevels_up--;
 		return (Node *) newnode;
 	}
-	return expression_tree_mutator(node, replace_rte_variables_mutator,
-								   (void *) context);
+	return expression_tree_mutator(node, replace_rte_variables_mutator, ctx);
 }

@@ -1230,9 +1230,10 @@ typedef struct
 } map_variable_attnos_context;
 
 static Node *
-map_variable_attnos_mutator(Node *node,
-							map_variable_attnos_context *context)
+map_variable_attnos_mutator(Node *node, void *ctx)
 {
+	map_variable_attnos_context *context = ctx;
+
 	if (node == NULL)
 		return NULL;
 	if (IsA(node, Var))
@@ -1343,13 +1344,12 @@ map_variable_attnos_mutator(Node *node,
 		context->sublevels_up++;
 		newnode = query_tree_mutator((Query *) node,
 									 map_variable_attnos_mutator,
-									 (void *) context,
+									 ctx,
 									 0);
 		context->sublevels_up--;
 		return (Node *) newnode;
 	}
-	return expression_tree_mutator(node, map_variable_attnos_mutator,
-								   (void *) context);
+	return expression_tree_mutator(node, map_variable_attnos_mutator, ctx);
 }
 
 Node *
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
index 0d6a295674..e72bf06a3c 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -109,7 +109,7 @@ static Query *QueryListGetPrimaryStmt(List *stmts);
 static void AcquireExecutorLocks(List *stmt_list, bool acquire);
 static void AcquirePlannerLocks(List *stmt_list, bool acquire);
 static void ScanQueryForLocks(Query *parsetree, bool acquire);
-static bool ScanQueryWalker(Node *node, bool *acquire);
+static bool ScanQueryWalker(Node *node, void *ctx);
 static TupleDesc PlanCacheComputeResultDesc(List *stmt_list);
 static void PlanCacheRelCallback(Datum arg, Oid relid);
 static void PlanCacheObjectCallback(Datum arg, int cacheid, uint32 hashvalue);
@@ -1879,8 +1879,10 @@ ScanQueryForLocks(Query *parsetree, bool acquire)
  * Walker to find sublink subqueries for ScanQueryForLocks
  */
 static bool
-ScanQueryWalker(Node *node, bool *acquire)
+ScanQueryWalker(Node *node, void *ctx)
 {
+	bool	   *acquire = ctx;
+
 	if (node == NULL)
 		return false;
 	if (IsA(node, SubLink))
@@ -1896,8 +1898,7 @@ ScanQueryWalker(Node *node, bool *acquire)
 	 * Do NOT recurse into Query nodes, because ScanQueryForLocks already
 	 * processed subselects of subselects for us.
 	 */
-	return expression_tree_walker(node, ScanQueryWalker,
-								  (void *) acquire);
+	return expression_tree_walker(node, ScanQueryWalker, ctx);
 }
 
 /*
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index 82925b4b63..6c88f4b7ed 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -239,7 +239,7 @@ extern PlanState *ExecInitNode(Plan *node, EState *estate, int eflags);
 extern void ExecSetExecProcNode(PlanState *node, ExecProcNodeMtd function);
 extern Node *MultiExecProcNode(PlanState *node);
 extern void ExecEndNode(PlanState *node);
-extern bool ExecShutdownNode(PlanState *node);
+extern bool ExecShutdownNode(PlanState *node, void *ctx);
 extern void ExecSetTupleBound(int64 tuples_needed, PlanState *child_node);

diff --git a/src/include/nodes/nodeFuncs.h b/src/include/nodes/nodeFuncs.h
index 93c60bde66..d0fcf6c0a3 100644
--- a/src/include/nodes/nodeFuncs.h
+++ b/src/include/nodes/nodeFuncs.h
@@ -15,6 +15,8 @@
 
 #include "nodes/parsenodes.h"
 
+struct PlanState;				/* avoid including execnodes.h too */
+
 
 /* flags bits for query_tree_walker and query_tree_mutator */
 #define QTW_IGNORE_RT_SUBQUERIES	0x01	/* subqueries in rtable */
@@ -32,6 +34,14 @@
 /* callback function for check_functions_in_node */
 typedef bool (*check_function_callback) (Oid func_id, void *context);
 
+typedef bool (*planstate_tree_walker_callback) (struct PlanState *planstate,
+												void *context);
 
 extern Oid	exprType(const Node *expr);
 extern int32 exprTypmod(const Node *expr);
@@ -129,34 +139,38 @@ get_notclausearg(const void *notclause)
 extern bool check_functions_in_node(Node *node, check_function_callback checker,
 									void *context);

 

 
 
-struct PlanState;
-extern bool planstate_tree_walker(struct PlanState *planstate, bool (*walker) (),
+extern bool planstate_tree_walker(struct PlanState *planstate,
+								  planstate_tree_walker_callback walker,
 								  void *context);
 
 #endif							/* NODEFUNCS_H */
diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h
index 1566f435b3..f62fa440f8 100644
--- a/src/include/optimizer/planmain.h
+++ b/src/include/optimizer/planmain.h
@@ -115,6 +115,6 @@ extern Plan *set_plan_references(PlannerInfo *root, Plan *plan);
 extern bool trivial_subqueryscan(SubqueryScan *plan);
 extern void record_plan_function_dependency(PlannerInfo *root, Oid funcid);
 extern void record_plan_type_dependency(PlannerInfo *root, Oid typid);
-extern bool extract_query_dependencies_walker(Node *node, PlannerInfo *root);
+extern bool extract_query_dependencies_walker(Node *node, void *ctx);
 
 #endif							/* PLANMAIN_H */
diff --git a/src/include/rewrite/rewriteManip.h b/src/include/rewrite/rewriteManip.h
index 98b9b3a288..f57eeef801 100644
--- a/src/include/rewrite/rewriteManip.h
+++ b/src/include/rewrite/rewriteManip.h
@@ -68,8 +68,7 @@ extern Node *replace_rte_variables(Node *node,
 								   replace_rte_variables_callback callback,
 								   void *callback_arg,
 								   bool *outer_hasSubLinks);
-extern Node *replace_rte_variables_mutator(Node *node,
-										   replace_rte_variables_context *context);
+extern Node *replace_rte_variables_mutator(Node *node, void *ctx);
 
 extern Node *map_variable_attnos(Node *node,
 								 int target_varno, int sublevels_up,

---

From: Thomas Munro <[email-masked]>
Date: Mon, 19 Sep 2022 10:16:24 +1200

> the data type safety that we're giving up in this version of the patch

But is it defined behaviour?

https://stackoverflow.com/questions/559581/casting-a-function-pointer-to-another-type

> it that way in the attached, though.)

Huh... wouldn't systems that pass arguments right-to-left on the stack
receive NULL for node?  That'd include the SysV i386 convention used
on Linux, *BSD etc.  But that can't be right or we'd know about it...

But certainly +1 for fixing that regardless.

---

From: Tom Lane <[email-masked]>
Date: Sun, 18 Sep 2022 23:39:38 -0400

Thomas Munro <[email-masked]> writes:
>> ... This is fairly annoying, in that it gives up the function

> https://stackoverflow.com/questions/559581/casting-a-function-pointer-to-another-type

Well, what we're talking about is substituting "void *" (which is
required to be compatible with "char *") for a struct pointer type.
Standards legalese aside, that could only be a problem if the platform
ABI handles "char *" differently from struct pointer types.  The last
architecture I can remember dealing with where that might actually be
a thing was the PDP-10.  Everybody has learned better since then, but
the C committee is apparently still intent on making the world safe
for crappy machine architectures.

Also, if you want to argue that "void *" is not compatible with struct
pointer types, then it's not real clear to me that we aren't full of
other spec violations, because we sure do a lot of casting across that
(and even more with this patch as it stands).

I don't have the slightest hesitation about saying that if there's
still an architecture out there that's like that, we won't support it.
I also note that our existing code in this area would break pretty
thoroughly on such a machine, so this isn't making it worse.

			regards, tom lane

---

From: Thomas Munro <[email-masked]>
Date: Mon, 19 Sep 2022 16:32:59 +1200

> thoroughly on such a machine, so this isn't making it worse.

Yeah, I don't expect it to be a practical problem on any real system
(that is, I don't expect any real calling convention to transfer a
struct T * argument in a different place than void *).  I just wanted
to mention that it's a new liberty.  It's one thing to cast struct T *
to void * and back before dereferencing, and another to cast a pointer
to a function that takes struct T * to a pointer to a function that
takes void * and call it.  I considered proposing that myself when
first reporting this problem, but fear of language lawyers put me off.

---

From: Tom Lane <[email-masked]>
Date: Mon, 19 Sep 2022 00:53:30 -0400

> to mention that it's a new liberty.

No, it's not, because the existing coding here is already assuming that.
The walker callbacks are generally declared as taking a "struct *"
second parameter, but expression_tree_walker et al think they are
passing a "void *" to them.  Even if a platform ABI had some weird
special rule about how to call functions that you don't know the
argument list for, it wouldn't fix this because the walkers sure do know
what their arguments are.  The only reason this code works today is that
in practice, "void *" *is* ABI-compatible with "struct *".

I'm not excited about creating a demonstrable opportunity for bugs
in order to make the code hypothetically more compatible with
hardware designs that are thirty years obsolete.  (Hypothetical
in the sense that there's little reason to believe there would
be no other problems.)

			regards, tom lane

---

From: Thomas Munro <[email-masked]>
Date: Mon, 19 Sep 2022 19:30:09 +1200

> in practice, "void *" *is* ABI-compatible with "struct *".

True.

> in the sense that there's little reason to believe there would

Fair enough.

---

From: Thomas Munro <[email-masked]>
Date: Mon, 19 Sep 2022 19:40:11 +1200

> on Linux, *BSD etc.  But that can't be right or we'd know about it...

I take that back after looking up some long forgotten details; it
happily ignores extra arguments.

---

From: Tom Lane <[email-masked]>
Date: Mon, 19 Sep 2022 10:00:05 -0400

> happily ignores extra arguments.

Yeah; the fact that no one has complained in several years seems to
indicate that there's not a problem on supported platforms.  Still,
unlike the quibbles over whether char and struct pointers are the
same, it seems clear that this is the sort of inconsistency that
C2x wants to forbid, presumably in the name of making the world
safe for more-efficient function calling code.  So I think we'd
better go fix ExecShutdownNode before somebody breaks it.

Whichever way we jump on the tree-walker API changes, those won't
be back-patchable.  I think the best we can do for the back branches
is add a configure test to use -Wno-deprecated-non-prototype
if available.  But the ExecShutdownNode change could be back-patched,
and I'm leaning to doing so even though that breakage is just
hypothetical today.

			regards, tom lane

---

From: Tom Lane <[email-masked]>
Date: Mon, 19 Sep 2022 14:10:12 -0400

Here's a second-generation patch that fixes the warnings by inserting
casts into a layer of macro wrappers.  I had supposed that this would
cause us to lose all detection of wrongly-chosen walker functions,
so I was very pleased to see this when applying it to yesterday's HEAD:

execProcnode.c:792:2: warning: cast from 'bool (*)(PlanState *)' (aka 'bool (*)(struct PlanState *)') to 'planstate_tree_walker_callback' (aka 'bool (*)(struct PlanState *, void *)') converts to incompatible function type [-Wcast-function-type]
        planstate_tree_walker(node, ExecShutdownNode, NULL);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../../src/include/nodes/nodeFuncs.h:180:33: note: expanded from macro 'planstate_tree_walker'
        planstate_tree_walker_impl(ps, (planstate_tree_walker_callback) (w), c)
                                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

So we've successfully suppressed the pedantic -Wdeprecated-non-prototype
warnings, and we have activated the actually-useful -Wcast-function-type
warnings, which seem to do exactly what we want in this context:

'-Wcast-function-type'
     Warn when a function pointer is cast to an incompatible function
     pointer.  In a cast involving function types with a variable
     argument list only the types of initial arguments that are provided
     are considered.  Any parameter of pointer-type matches any other
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     pointer-type.  Any benign differences in integral types are
     ^^^^^^^^^^^^
     ignored, like 'int' vs.  'long' on ILP32 targets.  Likewise type
     qualifiers are ignored.  The function type 'void (*) (void)' is
     special and matches everything, which can be used to suppress this
     warning.  In a cast involving pointer to member types this warning
     warns whenever the type cast is changing the pointer to member
     type.  This warning is enabled by '-Wextra'.

(That verbiage is from the gcc manual; clang seems to act the same
except that -Wcast-function-type is selected by -Wall, or perhaps is
even on by default.)

So I'm pretty pleased with this formulation: no caller changes are
needed, and it does exactly what we want warning-wise.

			regards, tom lane

index 3bac350bf5..724d076674 100644

 /*
@@ -1909,9 +1911,9 @@ check_functions_in_node(Node *node, check_function_callback checker,
  */
 
 bool
-expression_tree_walker(Node *node,
-					   bool (*walker) (),
-					   void *context)
+expression_tree_walker_impl(Node *node,
+							tree_walker_callback walker,
+							void *context)
 {
 	ListCell   *temp;
 
+#define LIST_WALK(l) expression_tree_walker_impl((Node *) (l), walker, context)
+
 	if (node == NULL)
 		return false;

 

 

 

 
 				/*

 

 

 

 

 

 
 				/*

 

 
 
 /*
@@ -2390,10 +2383,10 @@ expression_tree_walker(Node *node,
  * indicated items.  (More flag bits may be added as needed.)
  */
 bool
-query_tree_walker(Query *query,
-				  bool (*walker) (),
-				  void *context,
-				  int flags)
+query_tree_walker_impl(Query *query,
+					   tree_walker_callback walker,
+					   void *context,
+					   int flags)
 {
 	Assert(query != NULL && IsA(query, Query));

 
 	/*

 	if (!(flags & QTW_IGNORE_CTE_SUBQUERIES))
 	{
-		if (walker((Node *) query->cteList, context))
+		if (WALK(query->cteList))
 			return true;
 	}
 	if (!(flags & QTW_IGNORE_RANGE_TABLE))
@@ -2491,10 +2484,10 @@ query_tree_walker(Query *query,
  * its own.
  */
 bool
-range_table_walker(List *rtable,
-				   bool (*walker) (),
-				   void *context,
-				   int flags)
+range_table_walker_impl(List *rtable,
+						tree_walker_callback walker,
+						void *context,
+						int flags)
 {
 	ListCell   *rt;
 
@@ -2512,10 +2505,10 @@ range_table_walker(List *rtable,
  * Some callers even want to scan the expressions in individual RTEs.
  */
 bool
-range_table_entry_walker(RangeTblEntry *rte,
-						 bool (*walker) (),
-						 void *context,
-						 int flags)
+range_table_entry_walker_impl(RangeTblEntry *rte,
+							  tree_walker_callback walker,
+							  void *context,
+							  int flags)
 {
 	/*
 	 * Walkers might need to examine the RTE node itself either before or
@@ -2523,35 +2516,35 @@ range_table_entry_walker(RangeTblEntry *rte,
 	 * specify neither flag, the walker won't be called on the RTE at all.
 	 */
 	if (flags & QTW_EXAMINE_RTES_BEFORE)
-		if (walker(rte, context))
+		if (WALK(rte))
 			return true;
 
 	switch (rte->rtekind)
 	{
 		case RTE_RELATION:

 
 	return false;
@@ -2635,9 +2628,9 @@ range_table_entry_walker(RangeTblEntry *rte,
  */
 
 Node *
-expression_tree_mutator(Node *node,
-						Node *(*mutator) (),
-						void *context)
+expression_tree_mutator_impl(Node *node,
+							 tree_mutator_callback mutator,
+							 void *context)
 {
 	/*
 	 * The mutator has already decided not to modify the current node, but we
@@ -3366,10 +3359,10 @@ expression_tree_mutator(Node *node,
  * All modified substructure is safely copied in any case.
  */
 Query *
-query_tree_mutator(Query *query,
-				   Node *(*mutator) (),
-				   void *context,
-				   int flags)
+query_tree_mutator_impl(Query *query,
+						tree_mutator_callback mutator,
+						void *context,
+						int flags)
 {
 	Assert(query != NULL && IsA(query, Query));
 
@@ -3456,10 +3449,10 @@ query_tree_mutator(Query *query,
  * its own.
  */
 List *
-range_table_mutator(List *rtable,
-					Node *(*mutator) (),
-					void *context,
-					int flags)
+range_table_mutator_impl(List *rtable,
+						 tree_mutator_callback mutator,
+						 void *context,
+						 int flags)
 {
 	List	   *newrt = NIL;
 	ListCell   *rt;
@@ -3525,10 +3518,10 @@ range_table_mutator(List *rtable,
  * for the outermost Query node.
  */
 bool
-query_or_expression_tree_walker(Node *node,
-								bool (*walker) (),
-								void *context,
-								int flags)
+query_or_expression_tree_walker_impl(Node *node,
+									 tree_walker_callback walker,
+									 void *context,
+									 int flags)
 {
 	if (node && IsA(node, Query))
 		return query_tree_walker((Query *) node,
@@ -3536,7 +3529,7 @@ query_or_expression_tree_walker(Node *node,
 								 context,
 								 flags);
 	else
-		return walker(node, context);
+		return WALK(node);
 }
 
 /*
@@ -3548,10 +3541,10 @@ query_or_expression_tree_walker(Node *node,
  * for the outermost Query node.
  */
 Node *
-query_or_expression_tree_mutator(Node *node,
-								 Node *(*mutator) (),
-								 void *context,
-								 int flags)
+query_or_expression_tree_mutator_impl(Node *node,
+									  tree_mutator_callback mutator,
+									  void *context,
+									  int flags)
 {
 	if (node && IsA(node, Query))
 		return (Node *) query_tree_mutator((Query *) node,
@@ -3579,9 +3572,9 @@ query_or_expression_tree_mutator(Node *node,
  * statements can appear in CTEs.
  */
 bool
-raw_expression_tree_walker(Node *node,
-						   bool (*walker) (),
-						   void *context)
+raw_expression_tree_walker_impl(Node *node,
+								tree_walker_callback walker,
+								void *context)
 {
 	ListCell   *temp;

 

 

 

 

 

 

 

 

 

 

 
-				if (walker(stmt->infer, context))
+				if (WALK(stmt->infer))
 					return true;
-				if (walker(stmt->targetList, context))
+				if (WALK(stmt->targetList))
 					return true;
-				if (walker(stmt->whereClause, context))
+				if (WALK(stmt->whereClause))
 					return true;
 			}
 			break;
 		case T_CommonTableExpr:
 			/* search_clause and cycle_clause are not interesting here */
-			return walker(((CommonTableExpr *) node)->ctequery, context);
+			return WALK(((CommonTableExpr *) node)->ctequery);
 		default:
 			elog(ERROR, "unrecognized node type: %d",
 				 (int) nodeTag(node));
@@ -4085,13 +4078,16 @@ raw_expression_tree_walker(Node *node,
  * recurse into any sub-nodes it has.
  */
 bool
-planstate_tree_walker(PlanState *planstate,
-					  bool (*walker) (),
-					  void *context)
+planstate_tree_walker_impl(PlanState *planstate,
+						   planstate_tree_walker_callback walker,
+						   void *context)
 {
 	Plan	   *plan = planstate->plan;
 	ListCell   *lc;

 
 	/* righttree */

 

diff --git a/src/include/nodes/nodeFuncs.h b/src/include/nodes/nodeFuncs.h
index 93c60bde66..e223b053e6 100644
--- a/src/include/nodes/nodeFuncs.h
+++ b/src/include/nodes/nodeFuncs.h
@@ -15,6 +15,8 @@

 

 extern Oid	exprType(const Node *expr);
 extern int32 exprTypmod(const Node *expr);
@@ -129,34 +139,84 @@ get_notclausearg(const void *notclause)
 extern bool check_functions_in_node(Node *node, check_function_callback checker,
 									void *context);
 
-extern bool expression_tree_walker(Node *node, bool (*walker) (),
-								   void *context);
-extern Node *expression_tree_mutator(Node *node, Node *(*mutator) (),
-									 void *context);
-
-extern bool query_tree_walker(Query *query, bool (*walker) (),
-							  void *context, int flags);
-extern Query *query_tree_mutator(Query *query, Node *(*mutator) (),
-								 void *context, int flags);
-
-extern bool range_table_walker(List *rtable, bool (*walker) (),
-							   void *context, int flags);
-extern List *range_table_mutator(List *rtable, Node *(*mutator) (),
-								 void *context, int flags);
-
-extern bool range_table_entry_walker(RangeTblEntry *rte, bool (*walker) (),
-									 void *context, int flags);
-
-extern bool query_or_expression_tree_walker(Node *node, bool (*walker) (),
-											void *context, int flags);
-extern Node *query_or_expression_tree_mutator(Node *node, Node *(*mutator) (),
-											  void *context, int flags);
+/*
+ * The following functions are usually passed walker or mutator callbacks
+ * that are declared like "bool walker(Node *node, my_struct *context)"
+ * rather than "bool walker(Node *node, void *context)" as a strict reading
+ * of the C standard would require.  Changing the callbacks' declarations
+ * to "void *" would create serious hazards of passing them the wrong context
+ * struct type, so we respectfully decline to support the standard's position
+ * that a pointer to struct is incompatible with "void *".  Instead, silence
+ * related compiler warnings by inserting casts into these macro wrappers.
+ */
 
-extern bool raw_expression_tree_walker(Node *node, bool (*walker) (),
+#define expression_tree_walker(n, w, c) \
+	expression_tree_walker_impl(n, (tree_walker_callback) (w), c)
+#define expression_tree_mutator(n, m, c) \
+	expression_tree_mutator_impl(n, (tree_mutator_callback) (m), c)
+
+#define query_tree_walker(q, w, c, f) \
+	query_tree_walker_impl(q, (tree_walker_callback) (w), c, f)
+#define query_tree_mutator(q, m, c, f) \
+	query_tree_mutator_impl(q, (tree_mutator_callback) (m), c, f)
+
+#define range_table_walker(rt, w, c, f) \
+	range_table_walker_impl(rt, (tree_walker_callback) (w), c, f)
+#define range_table_mutator(rt, m, c, f) \
+	range_table_mutator_impl(rt, (tree_mutator_callback) (m), c, f)
+
+#define range_table_entry_walker(r, w, c, f) \
+	range_table_entry_walker_impl(r, (tree_walker_callback) (w), c, f)
+
+#define query_or_expression_tree_walker(n, w, c, f) \
+	query_or_expression_tree_walker_impl(n, (tree_walker_callback) (w), c, f)
+#define query_or_expression_tree_mutator(n, m, c, f) \
+	query_or_expression_tree_mutator_impl(n, (tree_mutator_callback) (m), c, f)
+
+#define raw_expression_tree_walker(n, w, c) \
+	raw_expression_tree_walker_impl(n, (tree_walker_callback) (w), c)
+
+#define planstate_tree_walker(ps, w, c) \
+	planstate_tree_walker_impl(ps, (planstate_tree_walker_callback) (w), c)
+
+extern bool expression_tree_walker_impl(Node *node,
+										tree_walker_callback walker,
+										void *context);
+extern Node *expression_tree_mutator_impl(Node *node,
+										  tree_mutator_callback mutator,
+										  void *context);
+
+extern bool query_tree_walker_impl(Query *query,
+								   tree_walker_callback walker,
+								   void *context, int flags);
+extern Query *query_tree_mutator_impl(Query *query,
+									  tree_mutator_callback mutator,
+									  void *context, int flags);
+
+extern bool range_table_walker_impl(List *rtable,
+									tree_walker_callback walker,
+									void *context, int flags);
+extern List *range_table_mutator_impl(List *rtable,
+									  tree_mutator_callback mutator,
+									  void *context, int flags);
+
+extern bool range_table_entry_walker_impl(RangeTblEntry *rte,
+										  tree_walker_callback walker,
+										  void *context, int flags);
+
+extern bool query_or_expression_tree_walker_impl(Node *node,
+												 tree_walker_callback walker,
+												 void *context, int flags);
+extern Node *query_or_expression_tree_mutator_impl(Node *node,
+												   tree_mutator_callback mutator,
+												   void *context, int flags);
+
+extern bool raw_expression_tree_walker_impl(Node *node,
+											tree_walker_callback walker,
+											void *context);
+
+extern bool planstate_tree_walker_impl(struct PlanState *planstate,
+									   planstate_tree_walker_callback walker,
 									   void *context);
 
-struct PlanState;
-								  void *context);
-
 #endif							/* NODEFUNCS_H */

---

From: Robert Haas <[email-masked]>
Date: Mon, 19 Sep 2022 14:11:40 -0400

> it that way in the attached, though.)

I think this was brain fade on my part ... or possibly on Amit
Kapila's part, but I believe it was probably me. I agree that it's
impressive that it actually seemed to work that way.

-- 
Robert Haas
EDB: http://www.enterprisedb.com

---

From: Tom Lane <[email-masked]>
Date: Tue, 20 Sep 2022 12:15:13 -0400

> except that -Wcast-function-type is selected by -Wall, or perhaps is

Nah, scratch that: the reason -Wcast-function-type is on is that
we explicitly enable it, and have done so since de8feb1f3 (v14).
I did not happen to see this warning with gcc because the test runs
I made with this patch already had c35ba141d, whereas I did my
clang test on another machine that wasn't quite up to HEAD.
So we should have good warning coverage for bogus walker signatures
on both compilers.

			regards, tom lane

---

From: Thomas Munro <[email-masked]>
Date: Mon, 12 Dec 2022 15:45:51 +1300

As visible on seawasp and locally (16/main branch nightly packages),
they decided to start warning about these casts with a new strict
variant of the warning.  Their discussion:

https://reviews.llvm.org/D134831

There are also a few other cases unrelated to this thread's original
problem, for example casts involving pg_funcptr_t, HashCompareFunc.  I
guess our options would be to turn that warning off, or reconsider and
try shoving the cast of "generic" arguments pointers down into the
functions?

---

From: Tom Lane <[email-masked]>
Date: Sun, 11 Dec 2022 22:07:05 -0500

> try shoving the cast of "generic" arguments pointers down into the

I'm for "turn the warning off".  Per previous discussion, adhering
strictly to that rule would make our code worse (less legible AND
less safe), not better.

			regards, tom lane

---

From: Thomas Munro <[email-masked]>
Date: Mon, 12 Dec 2022 16:43:41 +1300

> strictly to that rule would make our code worse (less legible AND

Alright, this seems to do the trick here.
From b01690ca859b5f27ece386577b7b9d9d7572b8d2 Mon Sep 17 00:00:00 2001
From: Thomas Munro <[email-masked]>
Date: Mon, 12 Dec 2022 16:28:24 +1300
Subject: [PATCH] Disable clang 16's -Wcast-function-type-strict.

Clang 16 is still in development, but seawasp reveals that it has
started warning about many of our casts of function pointers.  Disable
the new warning for now, since otherwise buildfarm animal seawasp fails.

May be back-patched with other Clang/LLVM 16 changes around release
time.

Discussion: https://postgr.es/m/CA%2BhUKGJvX%2BL3aMN84ksT-cGy08VHErRNip3nV-WmTx7f6Pqhyw%40mail.gmail.com
---
 configure    | 44 ++++++++++++++++++++++++++++++++++++++++++++
 configure.ac |  6 ++++++
 meson.build  |  3 +++
 3 files changed, 53 insertions(+)

diff --git a/configure b/configure
index 62f382c1d1..5025448a05 100755
--- a/configure
+++ b/configure
@@ -6611,6 +6611,50 @@ fi
   if test -n "$NOT_THE_CFLAGS"; then
     CFLAGS="$CFLAGS -Wno-stringop-truncation"
   fi
+  # Suppress clang 16's strict warnings about function casts
+  NOT_THE_CFLAGS=""
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC} supports -Wcast-function-type-strict, for NOT_THE_CFLAGS" >&5
+$as_echo_n "checking whether ${CC} supports -Wcast-function-type-strict, for NOT_THE_CFLAGS... " >&6; }
+if ${pgac_cv_prog_CC_cflags__Wcast_function_type_strict+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  pgac_save_CFLAGS=$CFLAGS
+pgac_save_CC=$CC
+CC=${CC}
+CFLAGS="${NOT_THE_CFLAGS} -Wcast-function-type-strict"
+ac_save_c_werror_flag=$ac_c_werror_flag
+ac_c_werror_flag=yes
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  pgac_cv_prog_CC_cflags__Wcast_function_type_strict=yes
+else
+  pgac_cv_prog_CC_cflags__Wcast_function_type_strict=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_c_werror_flag=$ac_save_c_werror_flag
+CFLAGS="$pgac_save_CFLAGS"
+CC="$pgac_save_CC"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_CC_cflags__Wcast_function_type_strict" >&5
+$as_echo "$pgac_cv_prog_CC_cflags__Wcast_function_type_strict" >&6; }
+if test x"$pgac_cv_prog_CC_cflags__Wcast_function_type_strict" = x"yes"; then
+  NOT_THE_CFLAGS="${NOT_THE_CFLAGS} -Wcast-function-type-strict"
+fi
+
+
+  if test -n "$NOT_THE_CFLAGS"; then
+    CFLAGS="$CFLAGS -Wno-cast-function-type-strict"
+  fi
 elif test "$ICC" = yes; then
   # Intel's compiler has a bug/misoptimization in checking for
   # division by NAN (NaN == 0), -mp1 fixes it, so add it to the CFLAGS.
diff --git a/configure.ac b/configure.ac
index cfb10f59ce..4cd328fc83 100644
--- a/configure.ac
+++ b/configure.ac
@@ -573,6 +573,12 @@ if test "$GCC" = yes -a "$ICC" = no; then
   if test -n "$NOT_THE_CFLAGS"; then
     CFLAGS="$CFLAGS -Wno-stringop-truncation"
   fi
+  # Suppress clang 16's strict warnings about function casts
+  NOT_THE_CFLAGS=""
+  PGAC_PROG_CC_VAR_OPT(NOT_THE_CFLAGS, [-Wcast-function-type-strict])
+  if test -n "$NOT_THE_CFLAGS"; then
+    CFLAGS="$CFLAGS -Wno-cast-function-type-strict"
+  fi
 elif test "$ICC" = yes; then
   # Intel's compiler has a bug/misoptimization in checking for
   # division by NAN (NaN == 0), -mp1 fixes it, so add it to the CFLAGS.
diff --git a/meson.build b/meson.build
index a62d8171cc..9df8685dfd 100644
--- a/meson.build
+++ b/meson.build
@@ -1773,6 +1773,9 @@ negative_warning_flags = [
   'format-truncation',
   'stringop-truncation',
 
+  # Suppress clang 16's strict warnings about function casts
+  'cast-function-type-strict',
+
   # To make warning_level=2 / -Wextra work, we'd need at least the following
   # 'clobbered',
   # 'missing-field-initializers',
-- 
2.35.1

---

From: Thomas Munro <[email-masked]>
Date: Tue, 13 Dec 2022 14:18:48 +1300

> Alright, this seems to do the trick here.

That did fix that problem.  But... seawasp also just recompiled its
compiler and picked up new opaque pointer API changes.  So no green
today.  I have more work to do to fix that, which might take some time
to get back to.

---

From: Andres Freund <[email-masked]>
Date: Thu, 22 May 2025 10:47:06 -0400

Hi,

> today.  I have more work to do to fix that, which might take some time

Presumably due to conflict resolution, this commit added an empty meson.build
to REL_13_STABLE. I'll remove that...

Greetings,

Andres Freund