diff --git a/src/snc/analysis.c b/src/snc/analysis.c
index 01e4e10846eb66d2385cc9a12f2a4ce1083083db..34cf14611108eb4cc9a5b425141dd60a3c4f1cb6 100644
--- a/src/snc/analysis.c
+++ b/src/snc/analysis.c
@@ -20,6 +20,7 @@ in the file LICENSE that is included with this distribution.
 #include "main.h"
 #include "expr.h"
 #include "builtin.h"
+#include "gen_code.h"
 #include "analysis.h"
 
 static const int impossible = 0;
@@ -97,7 +98,9 @@ static void analyse_funcdefs(Expr *prog)
 	{
 		Expr *d = f->funcdef_decl;
 		Var *var = d->extra.e_decl;
+		struct function_type *fun_type = &var->type->val.function;
 		Expr *p;
+		Token t;
 
 		assert(f->type == D_FUNCDEF);
 		if (var->type->tag != T_FUNCTION)
@@ -105,9 +108,9 @@ static void analyse_funcdefs(Expr *prog)
 			error_at_expr(d, "not a function type\n");
 			continue;
 		}
-		f->funcdef_params = var->type->val.function.param_decls;
-		assert(f->funcdef_params);	/* invariant enforced by syntax */
-		p = f->funcdef_params;
+
+		p = fun_type->param_decls;
+		assert(p);			/* invariant enforced by syntax */
 		if (p->extra.e_decl->type->tag == T_VOID)
 		{
 			/* no other params should be there */
@@ -120,9 +123,9 @@ static void analyse_funcdefs(Expr *prog)
 				error_at_expr(p, "void parameter should not have a name\n");
 			}
 			/* void means empty parameter list */
-			f->funcdef_params = var->type->val.function.param_decls = 0;
+			fun_type->param_decls = 0;
 		}
-		foreach(p, f->funcdef_params)
+		foreach(p, fun_type->param_decls)
 		{
 			/* check parameter has a name */
 			if (!p->extra.e_decl->name)
@@ -130,6 +133,25 @@ static void analyse_funcdefs(Expr *prog)
 				error_at_expr(p, "function parameter must have a name\n");
 			}
 		}
+		/* prepend "SEQ_VARS *const _seq_vars" to parameter list */
+		t.str = NM_VARS_ARG;
+		t.line = d->line_num;
+		t.file = d->src_file;
+		p = decl_add_base_type(
+			decl_create(t),
+			/* HACK! act as if "SEQ_VARS *const" were an identifier */
+			mk_foreign_type(F_TYPENAME, "SEQ_VARS *const")
+		);
+		fun_type->param_decls = link_expr(p, fun_type->param_decls);
+		/* prepend "SS_ID _seq_ss" to parameter list*/
+		t.str = NM_SS;
+		t.line = d->line_num;
+		t.file = d->src_file;
+		p = decl_add_base_type(
+			decl_create(t),
+			mk_foreign_type(F_TYPENAME, "SS_ID")
+		);
+		fun_type->param_decls = link_expr(p, fun_type->param_decls);
 		prog->prog_defns = link_expr(prog->prog_defns, d);
 	}
 }
diff --git a/src/snc/gen_code.c b/src/snc/gen_code.c
index 64e5a217a3a5758cd641ff17537d2fdae8312b2d..19ea8d0b5ce21d97776546a57393680e02b7d8cc 100644
--- a/src/snc/gen_code.c
+++ b/src/snc/gen_code.c
@@ -221,23 +221,15 @@ static void gen_user_var(Program *p)
 		}
 		gen_code("};\n");
 	}
+	/* function declarations are always global and static */
 	foreach (vp, p->prog->extra.e_prog->first)
 	{
 		if (vp->decl && vp->type->tag == T_FUNCTION)
 		{
-			Expr *param_decl;
-
 			gen_line_marker(vp->decl);
 			gen_code("static ");
-			gen_type(vp->type->val.function.return_type, "", vp->name);
-			gen_code("(SS_ID " NM_SS ", SEQ_VARS *const " NM_VARS_ARG);
-			foreach (param_decl, vp->type->val.function.param_decls)
-			{
-				Var *vp = param_decl->extra.e_decl;
-				gen_code(", ");
-				gen_var_decl(vp);
-			}
-			gen_code(");\n");
+			gen_var_decl(vp);
+			gen_code(";\n");
 		}
 	}
 	gen_code("\n");
diff --git a/src/snc/gen_ss_code.c b/src/snc/gen_ss_code.c
index 7538ab419758c8446957528571fa7242c8acb297..41be7815635f29b9b8f3af0f928c860251f41f48 100644
--- a/src/snc/gen_ss_code.c
+++ b/src/snc/gen_ss_code.c
@@ -908,20 +908,12 @@ static void gen_prog_exit_body(Expr *prog)
 
 static void gen_funcdef(Expr *fp)
 {
-	Expr *param_decl;
 	Var *vp = fp->funcdef_decl->extra.e_decl;
 
 	assert(fp->type == D_FUNCDEF);
 	gen_line_marker(vp->decl);
 	gen_code("static ");
-	gen_type(vp->type->val.function.return_type, "", vp->name);
-	gen_code("(SS_ID " NM_SS ", SEQ_VARS *const " NM_VARS_ARG);
-	foreach (param_decl,  fp->funcdef_params)
-	{
-		vp = param_decl->extra.e_decl;
-		gen_code(", ");
-		gen_var_decl(vp);
-	}
-	gen_code(")\n");
+	gen_var_decl(vp);
+	gen_code("\n");
 	gen_block(fp->funcdef_block, C_FUNC, 0);
 }
diff --git a/src/snc/snl.lem b/src/snc/snl.lem
index f61b7887efb473fcc18c0a6d2d3b3343f4fc65b8..aeb3cd5fa85893287373475f2d2338abb0805bce 100644
--- a/src/snc/snl.lem
+++ b/src/snc/snl.lem
@@ -480,7 +480,7 @@ functions(p) ::= .					{ p = 0; }
 functions(p) ::= functions(fs) function(f).		{ p = link_expr(fs, f); }
 
 function(p) ::= FUNCTION(l) basetype(t) declarator(d) block(b). {
-	p = expr(D_FUNCDEF, l, decl_add_base_type(d, t), 0, b);
+	p = expr(D_FUNCDEF, l, decl_add_base_type(d, t), b);
 }
 
 // Literal (C) code
diff --git a/src/snc/types.h b/src/snc/types.h
index ebedc9e2c303ae246ef0e647531f48d6532577cd..d9738e022ebd2deefa3005c79278010811f99d18 100644
--- a/src/snc/types.h
+++ b/src/snc/types.h
@@ -271,7 +271,7 @@ enum expr_type			/* description [child expressions...] */
 	D_ASSIGN,		/* assign statement [subscr,pvs] */
 	D_DECL,			/* variable declaration [init] */
 	D_ENTEX,		/* entry or exit statement [block] */
-	D_FUNCDEF,		/* function definition [decl,params,block] */
+	D_FUNCDEF,		/* function definition [decl,block] */
 	D_MONITOR,		/* monitor statement [subscr] */
 	D_OPTION,		/* option definition [] */
 	D_PROG,			/* whole program [param,defns,entry,statesets,exit,funcdefs,ccode] */
@@ -334,8 +334,7 @@ STATIC_ASSERT(NUM_EXPR_TYPES <= 8*sizeof(TypeMask));
 #define func_expr	children[0]
 #define func_args	children[1]
 #define funcdef_decl	children[0]
-#define funcdef_params	children[1]
-#define funcdef_block	children[2]
+#define funcdef_block	children[1]
 #define if_cond		children[0]
 #define if_then		children[1]
 #define if_else		children[2]
@@ -376,6 +375,8 @@ STATIC_ASSERT(NUM_EXPR_TYPES <= 8*sizeof(TypeMask));
 #define while_cond	children[0]
 #define while_stmt	children[1]
 
+#define funcdef_params	funcdef_decl->extra.e_decl->type->val.function.param_decls
+
 #ifndef expr_type_GLOBAL
 extern
 #endif
@@ -390,7 +391,7 @@ expr_type_info[]
 	{ "D_ASSIGN",	2 },
 	{ "D_DECL",	1 },
 	{ "D_ENTEX",	1 },
-	{ "D_FUNCDEF",	3 },
+	{ "D_FUNCDEF",	2 },
 	{ "D_MONITOR",	1 },
 	{ "D_OPTION",	0 },
 	{ "D_PROG",	7 },
diff --git a/src/snc/var_types.c b/src/snc/var_types.c
index e22e6839014e0627c3f7a28fbb414d02918787f8..5792d5cb75e1d63e56d528915f5b6a2bfdc9518e 100644
--- a/src/snc/var_types.c
+++ b/src/snc/var_types.c
@@ -354,12 +354,6 @@ static void gen_array_pointer(Type *t, enum type_tag last_tag, const char *prefi
 void gen_type(Type *t, const char *prefix, const char *name)
 {
     Type *bt = base_type(t);
-    Type *saved_bt = bt;
-
-    /* DIRTY HACK: overwrite parent pointer so we can use this for the return type of a function */
-    if (bt->tag == T_FUNCTION) {
-        bt = t->parent = bt->parent;
-    }
 
     switch (bt->tag) {
     case T_EVFLAG:
@@ -378,6 +372,4 @@ void gen_type(Type *t, const char *prefix, const char *name)
         assert(impossible);
     }
     gen_array_pointer(bt->parent, T_NONE, prefix, name);
-    /* DIRTY HACK: restore parent pointer */
-    t->parent = saved_bt;
 }