Index: src/AST/Decl.hpp
===================================================================
--- src/AST/Decl.hpp	(revision 24afc5313ce84b9962eaf6529d35b0fc0d0df58f)
+++ src/AST/Decl.hpp	(revision f3cc5b6512f55846804a909de3b8735e14b2adef)
@@ -30,4 +30,7 @@
 #include "Parser/ParseNode.h"  // for DeclarationNode::Aggregate
 
+// Must be included in *all* AST classes; should be #undef'd at the end of the file
+#define MUTATE_FRIEND template<typename node_t> friend auto mutate(const node_t * node);
+
 namespace ast {
 
@@ -55,4 +58,5 @@
 private:
 	Decl * clone() const override = 0;
+	MUTATE_FRIEND
 };
 
@@ -87,4 +91,5 @@
 private:
 	DeclWithType * clone() const override = 0;
+	MUTATE_FRIEND
 };
 
@@ -108,8 +113,5 @@
 private:
 	ObjectDecl * clone() const override { return new ObjectDecl{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	MUTATE_FRIEND
 };
 
@@ -135,8 +137,5 @@
 private:
 	FunctionDecl * clone() const override { return new FunctionDecl( *this ); }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	MUTATE_FRIEND
 };
 
@@ -157,4 +156,5 @@
 private:
 	NamedTypeDecl* clone() const override = 0;
+	MUTATE_FRIEND
 };
 
@@ -198,8 +198,5 @@
 private:
 	TypeDecl * clone() const override { return new TypeDecl{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	MUTATE_FRIEND
 };
 
@@ -216,8 +213,5 @@
 private:
 	TypedefDecl * clone() const override { return new TypedefDecl{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	MUTATE_FRIEND
 };
 
@@ -238,4 +232,8 @@
 	AggregateDecl* set_body( bool b ) { body = b; return this; }
 
+private:
+	AggregateDecl * clone() const override = 0;
+	MUTATE_FRIEND
+
 protected:
 	/// Produces a name for the kind of aggregate
@@ -260,8 +258,5 @@
 private:
 	StructDecl * clone() const override { return new StructDecl{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	MUTATE_FRIEND
 
 	std::string typeString() const override { return "struct"; }
@@ -278,8 +273,5 @@
 private:
 	UnionDecl * clone() const override { return new UnionDecl{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	MUTATE_FRIEND
 
 	std::string typeString() const override { return "union"; }
@@ -299,8 +291,5 @@
 private:
 	EnumDecl * clone() const override { return new EnumDecl{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	MUTATE_FRIEND
 
 	std::string typeString() const override { return "enum"; }
@@ -320,8 +309,5 @@
 private:
 	TraitDecl * clone() const override { return new TraitDecl{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	MUTATE_FRIEND
 
 	std::string typeString() const override { return "trait"; }
@@ -338,8 +324,5 @@
 private:
 	AsmDecl *clone() const override { return new AsmDecl( *this ); }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	MUTATE_FRIEND
 };
 
@@ -355,8 +338,5 @@
 private:
 	StaticAssertDecl * clone() const override { return new StaticAssertDecl( *this ); }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	MUTATE_FRIEND
 };
 
@@ -397,4 +377,6 @@
 }
 
+#undef MUTATE_FRIEND
+
 // Local Variables: //
 // tab-width: 4 //
Index: src/AST/Expr.hpp
===================================================================
--- src/AST/Expr.hpp	(revision 24afc5313ce84b9962eaf6529d35b0fc0d0df58f)
+++ src/AST/Expr.hpp	(revision f3cc5b6512f55846804a909de3b8735e14b2adef)
@@ -27,4 +27,7 @@
 #include "Visitor.hpp"
 
+// Must be included in *all* AST classes; should be #undef'd at the end of the file
+#define MUTATE_FRIEND template<typename node_t> friend auto mutate(const node_t * node);
+
 namespace ast {
 
@@ -127,4 +130,5 @@
 private:
 	Expr * clone() const override = 0;
+	MUTATE_FRIEND
 };
 
@@ -141,4 +145,5 @@
 private:
 	ApplicationExpr * clone() const override { return new ApplicationExpr{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -160,4 +165,5 @@
 private:
 	UntypedExpr * clone() const override { return new UntypedExpr{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -173,4 +179,5 @@
 private:
 	NameExpr * clone() const override { return new NameExpr{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -185,4 +192,5 @@
 private:
 	AddressExpr * clone() const override { return new AddressExpr{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -198,4 +206,5 @@
 private:
 	LabelAddressExpr * clone() const override { return new LabelAddressExpr{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -217,4 +226,5 @@
 private:
 	CastExpr * clone() const override { return new CastExpr{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -234,4 +244,5 @@
 private:
 	KeywordCastExpr * clone() const override { return new KeywordCastExpr{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -247,4 +258,5 @@
 private:
 	VirtualCastExpr * clone() const override { return new VirtualCastExpr{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -261,4 +273,5 @@
 private:
 	UntypedMemberExpr * clone() const override { return new UntypedMemberExpr{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -274,4 +287,5 @@
 private:
 	MemberExpr * clone() const override { return new MemberExpr{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -289,4 +303,5 @@
 private:
 	VariableExpr * clone() const override { return new VariableExpr{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -332,4 +347,5 @@
 private:
 	ConstantExpr * clone() const override { return new ConstantExpr{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -347,4 +363,5 @@
 private:
 	SizeofExpr * clone() const override { return new SizeofExpr{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -362,4 +379,5 @@
 private:
 	AlignofExpr * clone() const override { return new AlignofExpr{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -376,4 +394,5 @@
 private:
 	UntypedOffsetofExpr * clone() const override { return new UntypedOffsetofExpr{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -389,4 +408,5 @@
 private:
 	OffsetofExpr * clone() const override { return new OffsetofExpr{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -401,4 +421,5 @@
 private:
 	OffsetPackExpr * clone() const override { return new OffsetPackExpr{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -418,4 +439,5 @@
 private:
 	LogicalExpr * clone() const override { return new LogicalExpr{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -433,4 +455,5 @@
 private:
 	ConditionalExpr * clone() const override { return new ConditionalExpr{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -447,4 +470,5 @@
 private:
 	CommaExpr * clone() const override { return new CommaExpr{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -459,4 +483,5 @@
 private:
 	TypeExpr * clone() const override { return new TypeExpr{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -554,4 +579,6 @@
 }
 
+#undef MUTATE_FRIEND
+
 // Local Variables: //
 // tab-width: 4 //
Index: src/AST/Init.hpp
===================================================================
--- src/AST/Init.hpp	(revision 24afc5313ce84b9962eaf6529d35b0fc0d0df58f)
+++ src/AST/Init.hpp	(revision f3cc5b6512f55846804a909de3b8735e14b2adef)
@@ -23,4 +23,7 @@
 #include "Visitor.hpp"
 
+// Must be included in *all* AST classes; should be #undef'd at the end of the file
+#define MUTATE_FRIEND template<typename node_t> friend auto mutate(const node_t * node);
+
 namespace ast {
 
@@ -40,4 +43,5 @@
 private:
 	Designation* clone() const override { return new Designation{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -55,4 +59,5 @@
 private:
 	const Init * clone() const override = 0;
+	MUTATE_FRIEND
 };
 
@@ -69,8 +74,5 @@
 private:
 	SingleInit * clone() const override { return new SingleInit{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	MUTATE_FRIEND
 };
 
@@ -97,8 +99,5 @@
 private:
 	ListInit * clone() const override { return new ListInit{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	MUTATE_FRIEND
 };
 
@@ -120,8 +119,5 @@
 private:
 	ConstructorInit * clone() const override { return new ConstructorInit{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	MUTATE_FRIEND
 };
 
@@ -142,4 +138,6 @@
 }
 
+#undef MUTATE_FRIEND
+
 // Local Variables: //
 // tab-width: 4 //
Index: src/AST/Stmt.hpp
===================================================================
--- src/AST/Stmt.hpp	(revision 24afc5313ce84b9962eaf6529d35b0fc0d0df58f)
+++ src/AST/Stmt.hpp	(revision f3cc5b6512f55846804a909de3b8735e14b2adef)
@@ -26,4 +26,7 @@
 #include "Common/CodeLocation.h"
 
+// Must be included in *all* AST classes; should be #undef'd at the end of the file
+#define MUTATE_FRIEND template<typename node_t> friend auto mutate(const node_t * node);
+
 namespace ast {
 
@@ -35,12 +38,13 @@
 	std::vector<Label> labels;
 
-	Stmt( const CodeLocation& loc, std::vector<Label>&& labels = {} )
+	Stmt( const CodeLocation & loc, std::vector<Label> && labels = {} )
 	: ParseNode(loc), labels(std::move(labels)) {}
 
 	Stmt(const Stmt& o) : ParseNode(o), labels(o.labels) {}
 
-	const Stmt* accept( Visitor& v ) const override = 0;
-private:
-	Stmt* clone() const override = 0;
+	const Stmt * accept( Visitor & v ) const override = 0;
+private:
+	Stmt * clone() const override = 0;
+	MUTATE_FRIEND
 };
 
@@ -50,5 +54,5 @@
 	std::list<ptr<Stmt>> kids;
 
-	CompoundStmt(const CodeLocation& loc, std::list<ptr<Stmt>>&& ks = {} )
+	CompoundStmt(const CodeLocation & loc, std::list<ptr<Stmt>> && ks = {} )
 	: Stmt(loc), kids(std::move(ks)) {}
 
@@ -56,14 +60,11 @@
 	CompoundStmt( CompoundStmt&& o ) = default;
 
-	void push_back( Stmt* s ) { kids.emplace_back( s ); }
-	void push_front( Stmt* s ) { kids.emplace_front( s ); }
-
-	const CompoundStmt* accept( Visitor& v ) const override { return v.visit( this ); }
-private:
-	CompoundStmt* clone() const override { return new CompoundStmt{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	void push_back( Stmt * s ) { kids.emplace_back( s ); }
+	void push_front( Stmt * s ) { kids.emplace_front( s ); }
+
+	const CompoundStmt * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	CompoundStmt * clone() const override { return new CompoundStmt{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -71,14 +72,11 @@
 class NullStmt final : public Stmt {
 public:
-	NullStmt( const CodeLocation& loc, std::vector<Label>&& labels = {} )
+	NullStmt( const CodeLocation & loc, std::vector<Label> && labels = {} )
 	: Stmt(loc, std::move(labels)) {}
 
-	const NullStmt* accept( Visitor& v ) const override { return v.visit( this ); }
-private:
-	NullStmt* clone() const override { return new NullStmt{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	const NullStmt * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	NullStmt * clone() const override { return new NullStmt{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -90,11 +88,8 @@
 	ExprStmt( const CodeLocation & loc, const Expr * e ) : Stmt(loc), expr(e) {}
 
-	const Stmt * accept( Visitor& v ) const override { return v.visit( this ); }
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
 	ExprStmt * clone() const override { return new ExprStmt{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	MUTATE_FRIEND
 };
 
@@ -107,19 +102,16 @@
 	std::vector<Label> gotoLabels;
 
-	AsmStmt( const CodeLocation& loc, bool isVolatile, const Expr * instruction,
-		std::vector<ptr<Expr>>&& output, std::vector<ptr<Expr>>&& input,
-		std::vector<ptr<ConstantExpr>>&& clobber, std::vector<Label>&& gotoLabels,
-		std::vector<Label>&& labels = {})
+	AsmStmt( const CodeLocation & loc, bool isVolatile, const Expr * instruction,
+		std::vector<ptr<Expr>> && output, std::vector<ptr<Expr>> && input,
+		std::vector<ptr<ConstantExpr>> && clobber, std::vector<Label> && gotoLabels,
+		std::vector<Label> && labels = {})
 	: Stmt(loc, std::move(labels)), isVolatile(isVolatile), instruction(instruction),
 	  output(std::move(output)), input(std::move(input)), clobber(std::move(clobber)),
 	  gotoLabels(std::move(gotoLabels)) {}
 
-	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
-private:
-	AsmStmt* clone() const override { return new AsmStmt{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	AsmStmt * clone() const override { return new AsmStmt{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -128,15 +120,12 @@
 	std::string directive;
 
-	DirectiveStmt( const CodeLocation& loc, const std::string & directive,
-		std::vector<Label>&& labels = {} )
+	DirectiveStmt( const CodeLocation & loc, const std::string & directive,
+		std::vector<Label> && labels = {} )
 	: Stmt(loc, std::move(labels)), directive(directive) {}
 
-	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
-private:
-	DirectiveStmt* clone() const override { return new DirectiveStmt{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	DirectiveStmt * clone() const override { return new DirectiveStmt{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -148,17 +137,14 @@
 	std::vector<ptr<Stmt>> inits;
 
-	IfStmt( const CodeLocation& loc, const Expr* cond, const Stmt* thenPart,
-		Stmt * const elsePart, std::vector<ptr<Stmt>>&& inits,
-		std::vector<Label>&& labels = {} )
+	IfStmt( const CodeLocation & loc, const Expr * cond, const Stmt * thenPart,
+		Stmt * const elsePart, std::vector<ptr<Stmt>> && inits,
+		std::vector<Label> && labels = {} )
 	: Stmt(loc, std::move(labels)), cond(cond), thenPart(thenPart), elsePart(elsePart),
 	  inits(std::move(inits)) {}
 
-	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
-private:
-	IfStmt* clone() const override { return new IfStmt{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	IfStmt * clone() const override { return new IfStmt{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -168,15 +154,12 @@
 	std::vector<ptr<Stmt>> stmts;
 
-	SwitchStmt( const CodeLocation& loc, const Expr* cond, std::vector<ptr<Stmt>>&& stmts,
-		std::vector<Label>&& labels = {} )
+	SwitchStmt( const CodeLocation & loc, const Expr * cond, std::vector<ptr<Stmt>> && stmts,
+		std::vector<Label> && labels = {} )
 	: Stmt(loc, std::move(labels)), cond(cond), stmts(std::move(stmts)) {}
 
-	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
-private:
-	SwitchStmt* clone() const override { return new SwitchStmt{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	SwitchStmt * clone() const override { return new SwitchStmt{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -186,17 +169,14 @@
 	std::vector<ptr<Stmt>> stmts;
 
-    CaseStmt( const CodeLocation& loc, const Expr* cond, std::vector<ptr<Stmt>>&& stmts,
-        std::vector<Label>&& labels = {} )
-    : Stmt(loc, std::move(labels)), cond(cond), stmts(std::move(stmts)) {}
+	CaseStmt( const CodeLocation & loc, const Expr * cond, std::vector<ptr<Stmt>> && stmts,
+		std::vector<Label> && labels = {} )
+	: Stmt(loc, std::move(labels)), cond(cond), stmts(std::move(stmts)) {}
 
 	bool isDefault() { return !cond; }
 
-	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
-private:
-	CaseStmt* clone() const override { return new CaseStmt{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	CaseStmt * clone() const override { return new CaseStmt{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -208,16 +188,13 @@
 	bool isDoWhile;
 
-	WhileStmt( const CodeLocation& loc, const Expr* cond, const Stmt* body,
-		std::vector<ptr<Stmt>>&& inits, bool isDoWhile = false, std::vector<Label>&& labels = {} )
+	WhileStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body,
+		std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, std::vector<Label> && labels = {} )
 	: Stmt(loc, std::move(labels)), cond(cond), body(body), inits(std::move(inits)),
 	  isDoWhile(isDoWhile) {}
 
-	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
-private:
-	WhileStmt* clone() const override { return new WhileStmt{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	WhileStmt * clone() const override { return new WhileStmt{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -229,16 +206,13 @@
 	ptr<Stmt> body;
 
-	ForStmt( const CodeLocation& loc, std::vector<ptr<Stmt>>&& inits, const Expr* cond,
-		const Expr* inc, const Stmt* body, std::vector<Label>&& labels = {} )
+	ForStmt( const CodeLocation & loc, std::vector<ptr<Stmt>> && inits, const Expr * cond,
+		const Expr * inc, const Stmt * body, std::vector<Label> && labels = {} )
 	: Stmt(loc, std::move(labels)), inits(std::move(inits)), cond(cond), inc(inc),
 	  body(body) {}
 
-	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
-private:
-	ForStmt* clone() const override { return new ForStmt{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	ForStmt * clone() const override { return new ForStmt{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -253,8 +227,8 @@
 	Kind kind;
 
-	BranchStmt( const CodeLocation& loc, Kind kind, Label target,
-		std::vector<Label>&& labels = {} );
-	BranchStmt( const CodeLocation& loc, const Expr* computedTarget,
-		std::vector<Label>&& labels = {} )
+	BranchStmt( const CodeLocation & loc, Kind kind, Label target,
+		std::vector<Label> && labels = {} );
+	BranchStmt( const CodeLocation & loc, const Expr * computedTarget,
+		std::vector<Label> && labels = {} )
 	: Stmt(loc, std::move(labels)), originalTarget(loc), target(loc),
 	  computedTarget(computedTarget), kind(Goto) {}
@@ -262,11 +236,8 @@
 	const char * kindName() { return kindNames[kind]; }
 
-	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
-private:
-	BranchStmt* clone() const override { return new BranchStmt{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	BranchStmt * clone() const override { return new BranchStmt{ *this }; }
+	MUTATE_FRIEND
 
 	static const char * kindNames[kindEnd];
@@ -277,14 +248,11 @@
 	ptr<Expr> expr;
 
-	ReturnStmt( const CodeLocation& loc, const Expr* expr, std::vector<Label>&& labels = {} )
+	ReturnStmt( const CodeLocation & loc, const Expr * expr, std::vector<Label> && labels = {} )
 	: Stmt(loc, std::move(labels)), expr(expr) {}
 
-	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
-private:
-	ReturnStmt* clone() const override { return new ReturnStmt{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	ReturnStmt * clone() const override { return new ReturnStmt{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -297,15 +265,12 @@
 	Kind kind;
 
-	ThrowStmt( const CodeLocation& loc, Kind kind, const Expr* expr, const Expr* target,
-		std::vector<Label>&& labels = {} )
+	ThrowStmt( const CodeLocation & loc, Kind kind, const Expr * expr, const Expr * target,
+		std::vector<Label> && labels = {} )
 	: Stmt(loc, std::move(labels)), expr(expr), target(target), kind(kind) {}
 
-	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
-private:
-	ThrowStmt* clone() const override { return new ThrowStmt{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	ThrowStmt * clone() const override { return new ThrowStmt{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -316,16 +281,13 @@
 	ptr<FinallyStmt> finally;
 
-	TryStmt( const CodeLocation& loc, const CompoundStmt* body,
-		std::vector<ptr<CatchStmt>>&& handlers, const FinallyStmt* finally,
-		std::vector<Label>&& labels = {} )
+	TryStmt( const CodeLocation & loc, const CompoundStmt * body,
+		std::vector<ptr<CatchStmt>> && handlers, const FinallyStmt * finally,
+		std::vector<Label> && labels = {} )
 	: Stmt(loc, std::move(labels)), body(body), handlers(std::move(handlers)), finally(finally) {}
 
-	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
-private:
-	TryStmt* clone() const override { return new TryStmt{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	TryStmt * clone() const override { return new TryStmt{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -339,15 +301,12 @@
 	Kind kind;
 
-	CatchStmt( const CodeLocation& loc, Kind kind, const Decl* decl, const Expr* cond,
-		const Stmt* body, std::vector<Label>&& labels = {} )
+	CatchStmt( const CodeLocation & loc, Kind kind, const Decl * decl, const Expr * cond,
+		const Stmt * body, std::vector<Label> && labels = {} )
 	: Stmt(loc, std::move(labels)), decl(decl), cond(cond), body(body), kind(kind) {}
 
-	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
-private:
-	CatchStmt* clone() const override { return new CatchStmt{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	CatchStmt * clone() const override { return new CatchStmt{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -356,15 +315,12 @@
 	ptr<CompoundStmt> body;
 
-	FinallyStmt( const CodeLocation& loc, const CompoundStmt* body,
-		std::vector<Label>&& labels = {} )
+	FinallyStmt( const CodeLocation & loc, const CompoundStmt * body,
+		std::vector<Label> && labels = {} )
 	: Stmt(loc, std::move(labels)), body(body) {}
 
-	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
-private:
-	FinallyStmt* clone() const override { return new FinallyStmt{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	FinallyStmt * clone() const override { return new FinallyStmt{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -397,14 +353,11 @@
 	OrElse orElse;
 
-	WaitForStmt( const CodeLocation& loc, std::vector<Label>&& labels = {} )
+	WaitForStmt( const CodeLocation & loc, std::vector<Label> && labels = {} )
 	: Stmt(loc, std::move(labels)) {}
 
-	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
-private:
-	WaitForStmt* clone() const override { return new WaitForStmt{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	WaitForStmt * clone() const override { return new WaitForStmt{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -414,15 +367,12 @@
 	ptr<Stmt> stmt;
 
-	WithStmt( const CodeLocation& loc, std::vector<ptr<Expr>>&& exprs, const Stmt* stmt,
-		std::vector<Label>&& labels = {} )
+	WithStmt( const CodeLocation & loc, std::vector<ptr<Expr>> && exprs, const Stmt * stmt,
+		std::vector<Label> && labels = {} )
 	: Stmt(loc, std::move(labels)), exprs(std::move(exprs)), stmt(stmt) {}
 
-	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
-private:
-	WithStmt* clone() const override { return new WithStmt{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	WithStmt * clone() const override { return new WithStmt{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -431,14 +381,11 @@
 	ptr<Decl> decl;
 
-	DeclStmt( const CodeLocation& loc, const Decl* decl, std::vector<Label>&& labels = {} )
+	DeclStmt( const CodeLocation & loc, const Decl * decl, std::vector<Label> && labels = {} )
 	: Stmt(loc, std::move(labels)), decl(decl) {}
 
-	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
-private:
-	DeclStmt* clone() const override { return new DeclStmt{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	DeclStmt * clone() const override { return new DeclStmt{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -447,15 +394,12 @@
 	readonly<Stmt> callStmt;
 
-	ImplicitCtorDtorStmt( const CodeLocation& loc, const Stmt* callStmt,
-		std::vector<Label>&& labels = {} )
+	ImplicitCtorDtorStmt( const CodeLocation & loc, const Stmt * callStmt,
+		std::vector<Label> && labels = {} )
 	: Stmt(loc, std::move(labels)), callStmt(callStmt) {}
 
-	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
-private:
-	ImplicitCtorDtorStmt* clone() const override { return new ImplicitCtorDtorStmt{ *this }; }
-
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	ImplicitCtorDtorStmt * clone() const override { return new ImplicitCtorDtorStmt{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -510,4 +454,6 @@
 }
 
+#undef MUTATE_FRIEND
+
 // Local Variables: //
 // tab-width: 4 //
Index: src/AST/Type.hpp
===================================================================
--- src/AST/Type.hpp	(revision 24afc5313ce84b9962eaf6529d35b0fc0d0df58f)
+++ src/AST/Type.hpp	(revision f3cc5b6512f55846804a909de3b8735e14b2adef)
@@ -29,4 +29,7 @@
 #include "Visitor.hpp"
 
+// Must be included in *all* AST classes; should be #undef'd at the end of the file
+#define MUTATE_FRIEND template<typename node_t> friend auto mutate(const node_t * node);
+
 namespace ast {
 
@@ -70,4 +73,5 @@
 private:
 	virtual Type * clone() const override = 0;
+	MUTATE_FRIEND
 };
 
@@ -84,4 +88,5 @@
 private:
 	VoidType * clone() const override { return new VoidType{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -146,4 +151,5 @@
 private:
 	BasicType * clone() const override { return new BasicType{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -176,4 +182,5 @@
 private:
 	PointerType * clone() const override { return new PointerType{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -197,4 +204,5 @@
 private:
 	ArrayType * clone() const override { return new ArrayType{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -216,4 +224,5 @@
 private:
 	ReferenceType * clone() const override { return new ReferenceType{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -230,4 +239,5 @@
 private:
 	QualifiedType * clone() const override { return new QualifiedType{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -245,4 +255,5 @@
 private:
 	virtual ParameterizedType * clone() const override = 0;
+	MUTATE_FRIEND
 };
 
@@ -274,4 +285,5 @@
 private:
 	FunctionType * clone() const override { return new FunctionType{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -295,4 +307,5 @@
 private:
 	virtual ReferenceToType * clone() const override = 0;
+	MUTATE_FRIEND
 
 protected:
@@ -319,4 +332,5 @@
 private:
 	StructInstType * clone() const override { return new StructInstType{ *this }; }
+	MUTATE_FRIEND
 
 	std::string typeString() const override { return "struct"; }
@@ -341,4 +355,5 @@
 private:
 	UnionInstType * clone() const override { return new UnionInstType{ *this }; }
+	MUTATE_FRIEND
 
 	std::string typeString() const override { return "union"; }
@@ -363,4 +378,5 @@
 private:
 	EnumInstType * clone() const override { return new EnumInstType{ *this }; }
+	MUTATE_FRIEND
 
 	std::string typeString() const override { return "enum"; }
@@ -386,4 +402,5 @@
 private:
 	TraitInstType * clone() const override { return new TraitInstType{ *this }; }
+	MUTATE_FRIEND
 
 	std::string typeString() const override { return "trait"; }
@@ -414,4 +431,5 @@
 private:
 	TypeInstType * clone() const override { return new TypeInstType{ *this }; }
+	MUTATE_FRIEND
 
 	std::string typeString() const override { return "type"; }
@@ -442,4 +460,5 @@
 private:
 	TupleType * clone() const override { return new TupleType{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -456,4 +475,5 @@
 private:
 	TypeofType * clone() const override { return new TypeofType{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -466,4 +486,5 @@
 private:
 	VarArgsType * clone() const override { return new VarArgsType{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -475,5 +496,6 @@
 	const Type * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
-	ZeroType * clone() const override { return new ZeroType{ *this }; }	
+	ZeroType * clone() const override { return new ZeroType{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -486,4 +508,5 @@
 private:
 	OneType * clone() const override { return new OneType{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -496,4 +519,5 @@
 private:
 	GlobalScopeType * clone() const override { return new GlobalScopeType{ *this }; }
+	MUTATE_FRIEND
 };
 
@@ -546,4 +570,6 @@
 }
 
+#undef MUTATE_FRIEND
+
 // Local Variables: //
 // tab-width: 4 //
