Index: src/AST/Stmt.hpp
===================================================================
--- src/AST/Stmt.hpp	(revision 8a5530c3a15f736eaece69b227492df67f2bbd89)
+++ src/AST/Stmt.hpp	(revision 204358ba15701854d627778a1f03396f1a433f9c)
@@ -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 //
