--- /dev/null	Fri Dec 21 15:00:28 2018
+++ new/usr/src/tools/smatch/src/smatch_recurse.c	Fri Dec 21 15:00:28 2018
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2013 Oracle.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
+ */
+
+#include "smatch.h"
+
+#define RECURSE_LIMIT 10
+
+static int recurse(struct expression *expr,
+		   int (func)(struct expression *expr, void *p),
+		   void *param, int nr)
+{
+	int ret;
+
+	if (!expr)
+		return 0;
+
+	ret = func(expr, param);
+	if (ret)
+		return ret;
+
+	if (nr > RECURSE_LIMIT)
+		return -1;
+	nr++;
+
+	switch (expr->type) {
+	case EXPR_PREOP:
+		ret = recurse(expr->unop, func, param, nr);
+		break;
+	case EXPR_POSTOP:
+		ret = recurse(expr->unop, func, param, nr);
+		break;
+	case EXPR_STATEMENT:
+		return -1;
+		break;
+	case EXPR_LOGICAL:
+	case EXPR_COMPARE:
+	case EXPR_BINOP:
+	case EXPR_COMMA:
+		ret = recurse(expr->left, func, param, nr);
+		if (ret)
+			return ret;
+		ret = recurse(expr->right, func, param, nr);
+		break;
+	case EXPR_ASSIGNMENT:
+		ret = recurse(expr->right, func, param, nr);
+		if (ret)
+			return ret;
+		ret = recurse(expr->left, func, param, nr);
+		break;
+	case EXPR_DEREF:
+		ret = recurse(expr->deref, func, param, nr);
+		break;
+	case EXPR_SLICE:
+		ret = recurse(expr->base, func, param, nr);
+		break;
+	case EXPR_CAST:
+	case EXPR_FORCE_CAST:
+		ret = recurse(expr->cast_expression, func, param, nr);
+		break;
+	case EXPR_SIZEOF:
+	case EXPR_OFFSETOF:
+	case EXPR_ALIGNOF:
+		break;
+	case EXPR_CONDITIONAL:
+	case EXPR_SELECT:
+		ret = recurse(expr->conditional, func, param, nr);
+		if (ret)
+			return ret;
+		ret = recurse(expr->cond_true, func, param, nr);
+		if (ret)
+			return ret;
+		ret = recurse(expr->cond_false, func, param, nr);
+		break;
+	case EXPR_CALL:
+		return -1;
+		break;
+	case EXPR_INITIALIZER:
+		return -1;
+		break;
+	case EXPR_IDENTIFIER:
+		ret = recurse(expr->ident_expression, func, param, nr);
+		break;
+	case EXPR_INDEX:
+		ret = recurse(expr->idx_expression, func, param, nr);
+		break;
+	case EXPR_POS:
+		ret = recurse(expr->init_expr, func, param, nr);
+		break;
+	case EXPR_SYMBOL:
+	case EXPR_STRING:
+	case EXPR_VALUE:
+		break;
+	default:
+		return -1;
+		break;
+	};
+	return ret;
+}
+
+static int has_symbol_helper(struct expression *expr, void *_sym)
+{
+	struct symbol *sym = _sym;
+
+	if (!expr || expr->type != EXPR_SYMBOL)
+		return 0;
+	if (expr->symbol == sym)
+		return 1;
+	return 0;
+}
+
+int has_symbol(struct expression *expr, struct symbol *sym)
+{
+	return recurse(expr, has_symbol_helper, sym, 0);
+}
+
+struct expr_name_sym {
+	struct expression *expr;
+	char *name;
+	struct symbol *sym;
+};
+
+static int has_var_helper(struct expression *expr, void *_var)
+{
+	struct expr_name_sym *xns = _var;
+	char *name;
+	struct symbol *sym;
+	int matched = 0;
+
+	if (!expr)
+		return 0;
+	if (expr->type != xns->expr->type)
+		return 0;
+	// I hope this is defined for everything?  It should work, right?
+	if (expr->op != xns->expr->op)
+		return 0;
+
+	name = expr_to_var_sym(expr, &sym);
+	if (!name || !sym)
+		goto free;
+	if (sym == xns->sym && strcmp(name, xns->name) == 0)
+		matched = 1;
+free:
+	free_string(name);
+	return matched;
+}
+
+int has_variable(struct expression *expr, struct expression *var)
+{
+	struct expr_name_sym xns;
+	int ret = -1;
+
+	xns.expr = var;
+	xns.name = expr_to_var_sym(var, &xns.sym);
+	if (!xns.name || !xns.sym)
+		goto free;
+	ret = recurse(expr, has_var_helper, &xns, 0);
+free:
+	free_string(xns.name);
+	return ret;
+}
+
+static int has_inc_dec_helper(struct expression *expr, void *unused)
+{
+	if (!expr)
+		return 0;
+	if (expr->type != EXPR_PREOP && expr->type != EXPR_POSTOP)
+		return 0;
+	if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
+		return 1;
+	return 0;
+}
+
+int has_inc_dec(struct expression *expr)
+{
+	return recurse(expr, has_inc_dec_helper, NULL, 0);
+}
+
