Index: src/AST/Attribute.hpp
===================================================================
--- src/AST/Attribute.hpp	(revision 1fb7bfd9039e83e68b46670a2664f5a59ccf6cbc)
+++ src/AST/Attribute.hpp	(revision 87701b607d65c7537ed3e6026229861ab1667c6b)
@@ -50,16 +50,7 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
-
-
-//=================================================================================================
-/// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency
-/// remove only if there is a better solution
-/// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with
-/// forward declarations
-inline void increment( const class Attribute * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class Attribute * node, Node::ref_type ref ) { node->decrement( ref ); }
 }
 
Index: src/AST/Convert.cpp
===================================================================
--- src/AST/Convert.cpp	(revision 1fb7bfd9039e83e68b46670a2664f5a59ccf6cbc)
+++ src/AST/Convert.cpp	(revision 87701b607d65c7537ed3e6026229861ab1667c6b)
@@ -158,5 +158,5 @@
 		decl->parent = parent;
 		decl->body   = old->body;
-		decl->parameters = params;
+		decl->params = params;
 		decl->members    = members;
 		decl->extension  = old->extension;
@@ -181,5 +181,5 @@
 		decl->parent = parent;
 		decl->body   = old->body;
-		decl->parameters = params;
+		decl->params = params;
 		decl->members    = members;
 		decl->extension  = old->extension;
@@ -204,5 +204,5 @@
 		decl->parent = parent;
 		decl->body   = old->body;
-		decl->parameters = params;
+		decl->params = params;
 		decl->members    = members;
 		decl->extension  = old->extension;
@@ -230,5 +230,5 @@
 
 		decl->assertions = asserts;
-		decl->parameters = params;
+		decl->params     = params;
 		decl->extension  = old->extension;
 		decl->uniqueId   = old->uniqueId;
Index: src/AST/Decl.cpp
===================================================================
--- src/AST/Decl.cpp	(revision 1fb7bfd9039e83e68b46670a2664f5a59ccf6cbc)
+++ src/AST/Decl.cpp	(revision 87701b607d65c7537ed3e6026229861ab1667c6b)
@@ -20,7 +20,10 @@
 #include <unordered_map>
 
+#include "Common/utility.h"
+
 #include "Fwd.hpp"             // for UniqueId
 #include "Init.hpp"
 #include "Node.hpp"            // for readonly
+#include "Type.hpp"            // for readonly
 #include "Parser/ParseNode.h"  // for DeclarationNode
 
@@ -47,6 +50,6 @@
 // --- FunctionDecl
 
-const Type * FunctionDecl::get_type() const override { return type.get(); }
-void FunctionDecl::set_type(Type * t) override { type = strict_dynamic_cast< FunctionType* >( t ); }
+const Type * FunctionDecl::get_type() const { return type.get(); }
+void FunctionDecl::set_type(Type * t) { type = strict_dynamic_cast< FunctionType* >( t ); }
 
 // --- TypeDecl
@@ -75,5 +78,5 @@
 			const ObjectDecl* field = strict_dynamic_cast< const ObjectDecl* >( member );
 			if ( field->init ) {
-				const SingleInit* init = strict_dynamic_cast< const SingleInit* >( field->init );
+				const SingleInit * init = strict_dynamic_cast< const SingleInit* >( field->init.get() );
 				auto result = eval( init->value );
 				if ( ! result.second ) {
Index: src/AST/Decl.hpp
===================================================================
--- src/AST/Decl.hpp	(revision 1fb7bfd9039e83e68b46670a2664f5a59ccf6cbc)
+++ src/AST/Decl.hpp	(revision 87701b607d65c7537ed3e6026229861ab1667c6b)
@@ -111,5 +111,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
@@ -138,5 +138,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
@@ -201,5 +201,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
@@ -219,5 +219,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
@@ -263,5 +263,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 
 	std::string typeString() const override { return "struct"; }
@@ -281,5 +281,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 
 	std::string typeString() const override { return "union"; }
@@ -302,5 +302,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 
 	std::string typeString() const override { return "enum"; }
@@ -323,5 +323,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 
 	std::string typeString() const override { return "trait"; }
@@ -341,5 +341,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
@@ -358,40 +358,6 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
-};
-
-//=================================================================================================
-/// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency
-/// remove only if there is a better solution
-/// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with
-/// forward declarations
-inline void increment( const class Decl * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class Decl * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class DeclWithType * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class DeclWithType * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class ObjectDecl * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class ObjectDecl * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class FunctionDecl * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class FunctionDecl * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class AggregateDecl * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class AggregateDecl * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class StructDecl * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class StructDecl * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class UnionDecl * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class UnionDecl * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class EnumDecl * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class EnumDecl * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class TraitDecl * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class TraitDecl * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class NamedTypeDecl * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class NamedTypeDecl * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class TypeDecl * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class TypeDecl * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class TypedefDecl * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class TypedefDecl * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class AsmDecl * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class AsmDecl * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class StaticAssertDecl * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class StaticAssertDecl * node, Node::ref_type ref ) { node->decrement(ref); }
+	friend node_t * mutate(const node_t * node);
+};
 
 }
Index: src/AST/Expr.cpp
===================================================================
--- src/AST/Expr.cpp	(revision 1fb7bfd9039e83e68b46670a2664f5a59ccf6cbc)
+++ src/AST/Expr.cpp	(revision 87701b607d65c7537ed3e6026229861ab1667c6b)
@@ -30,7 +30,7 @@
 // --- ApplicationExpr
 
-ApplicationExpr::ApplicationExpr( const CodeLocation & loc, const Expr * f, 
-	std::vector<ptr<Expr>> && as ) 
-: Expr( loc ), func( f ), args( std::move(args) ) {
+ApplicationExpr::ApplicationExpr( const CodeLocation & loc, const Expr * f,
+	std::vector<ptr<Expr>> && as )
+: Expr( loc ), func( f ), args( std::move(as) ) {
 	// ensure that `ApplicationExpr` result type is `FuncExpr`
 	const PointerType * pt = strict_dynamic_cast< const PointerType * >( f->result.get() );
@@ -46,6 +46,6 @@
 	assert( arg );
 
-	UntypedExpr * ret = new UntypedExpr{ 
-		loc, new NameExpr{loc, "*?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ arg } } 
+	UntypedExpr * ret = new UntypedExpr{
+		loc, new NameExpr{loc, "*?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ arg } }
 	};
 	if ( const Type * ty = arg->result ) {
@@ -57,5 +57,5 @@
 			ret->result = new ReferenceType{ base };
 		} else {
-			// references have been removed, in which case dereference returns an lvalue of the 
+			// references have been removed, in which case dereference returns an lvalue of the
 			// base type
 			ret->result.set_and_mutate( base )->set_lvalue( true );
@@ -110,5 +110,5 @@
 		} else {
 			// taking address of non-lvalue, must be a reference, loses one layer of reference
-			if ( const ReferenceType * refType = 
+			if ( const ReferenceType * refType =
 					dynamic_cast< const ReferenceType * >( arg->result.get() ) ) {
 				Type * res = addrType( refType->base );
@@ -116,5 +116,5 @@
 				result = res;
 			} else {
-				SemanticError( loc, arg->result, 
+				SemanticError( loc, arg->result,
 					"Attempt to take address of non-lvalue expression: " );
 			}
@@ -126,10 +126,10 @@
 
 // label address always has type `void*`
-LabelAddressExpr::LabelAddressExpr( const CodeLocation & loc, Label && a ) 
+LabelAddressExpr::LabelAddressExpr( const CodeLocation & loc, Label && a )
 : Expr( loc, new PointerType{ new VoidType{} } ), arg( a ) {}
 
 // --- CastExpr
 
-CastExpr::CastExpr( const CodeLocation & loc, const Expr * a, GeneratedFlag g ) 
+CastExpr::CastExpr( const CodeLocation & loc, const Expr * a, GeneratedFlag g )
 : Expr( loc, new VoidType{} ), arg( a ), isGenerated( g ) {}
 
@@ -167,5 +167,5 @@
 }
 
-VariableExpr * VariableExpr::functionPointer( 
+VariableExpr * VariableExpr::functionPointer(
 		const CodeLocation & loc, const FunctionDecl * decl ) {
 	// wrap usually-determined result type in a pointer
@@ -200,21 +200,21 @@
 
 ConstantExpr * ConstantExpr::from_bool( const CodeLocation & loc, bool b ) {
-	return new ConstantExpr{ 
+	return new ConstantExpr{
 		loc, new BasicType{ BasicType::Bool }, b ? "1" : "0", (unsigned long long)b };
 }
 
 ConstantExpr * ConstantExpr::from_char( const CodeLocation & loc, char c ) {
-	return new ConstantExpr{ 
+	return new ConstantExpr{
 		loc, new BasicType{ BasicType::Char }, std::to_string( c ), (unsigned long long)c };
 }
 
 ConstantExpr * ConstantExpr::from_int( const CodeLocation & loc, int i ) {
-	return new ConstantExpr{ 
+	return new ConstantExpr{
 		loc, new BasicType{ BasicType::SignedInt }, std::to_string( i ), (unsigned long long)i };
 }
 
 ConstantExpr * ConstantExpr::from_ulong( const CodeLocation & loc, unsigned long i ) {
-	return new ConstantExpr{ 
-		loc, new BasicType{ BasicType::LongUnsignedInt }, std::to_string( i ), 
+	return new ConstantExpr{
+		loc, new BasicType{ BasicType::LongUnsignedInt }, std::to_string( i ),
 		(unsigned long long)i };
 }
@@ -227,5 +227,5 @@
 	return new ConstantExpr{
 		loc,
-		new ArrayType{ 
+		new ArrayType{
 			new BasicType{ BasicType::Char, CV::Const },
 			ConstantExpr::from_int( loc, s.size() + 1 /* null terminator */ ),
@@ -258,5 +258,5 @@
 // --- UntypedOffsetofExpr
 
-UntypedOffsetofExpr::UntypedOffsetofExpr( 
+UntypedOffsetofExpr::UntypedOffsetofExpr(
 	const CodeLocation & loc, const Type * ty, const std::string & mem )
 : Expr( loc, new BasicType{ BasicType::LongUnsignedInt } ), type( ty ), member( mem ) {
@@ -275,6 +275,6 @@
 
 OffsetPackExpr::OffsetPackExpr( const CodeLocation & loc, const StructInstType * ty )
-: Expr( loc, new ArrayType{ 
-	new BasicType{ BasicType::LongUnsignedInt }, nullptr, FixedLen, DynamicDim } 
+: Expr( loc, new ArrayType{
+	new BasicType{ BasicType::LongUnsignedInt }, nullptr, FixedLen, DynamicDim }
 ), type( ty ) {
 	assert( type );
@@ -283,5 +283,5 @@
 // --- LogicalExpr
 
-LogicalExpr::LogicalExpr( 
+LogicalExpr::LogicalExpr(
 	const CodeLocation & loc, const Expr * a1, const Expr * a2, LogicalFlag ia )
 : Expr( loc, new BasicType{ BasicType::SignedInt } ), arg1( a1 ), arg2( a2 ), isAnd( ia ) {}
Index: src/AST/Expr.hpp
===================================================================
--- src/AST/Expr.hpp	(revision 1fb7bfd9039e83e68b46670a2664f5a59ccf6cbc)
+++ src/AST/Expr.hpp	(revision 87701b607d65c7537ed3e6026229861ab1667c6b)
@@ -129,5 +129,5 @@
 };
 
-/// The application of a function to a set of parameters. 
+/// The application of a function to a set of parameters.
 /// Post-resolver form of `UntypedExpr`
 class ApplicationExpr final : public Expr {
@@ -209,5 +209,5 @@
 	GeneratedFlag isGenerated;
 
-	CastExpr( const CodeLocation & loc, const Expr * a, const Type * to, 
+	CastExpr( const CodeLocation & loc, const Expr * a, const Type * to,
 		GeneratedFlag g = GeneratedCast ) : Expr( loc, to ), arg( a ), isGenerated( g ) {}
 	/// Cast-to-void
@@ -296,5 +296,5 @@
 		unsigned long long ival;
 		double dval;
-		
+
 		Val( unsigned long long i ) : ival( i ) {}
 		Val( double d ) : dval( d ) {}
@@ -303,10 +303,10 @@
 	std::string rep;
 
-	ConstantExpr( 
+	ConstantExpr(
 		const CodeLocation & loc, const Type * ty, const std::string & r, unsigned long long v )
 	: Expr( loc, ty ), val( v ), rep( r ) {}
 	ConstantExpr( const CodeLocation & loc, const Type * ty, const std::string & r, double v )
 	: Expr( loc, ty ), val( v ), rep( r ) {}
-	
+
 	/// Gets the value of this constant as an integer
 	long long int intValue() const;
@@ -441,5 +441,5 @@
 	ptr<Expr> arg2;
 
-	CommaExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2 ) 
+	CommaExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2 )
 	: Expr( loc ), arg1( a1 ), arg2( a2 ) {}
 
@@ -466,90 +466,7 @@
 public:
 	ptr<Expr> inout;
-	ptr<Expr> constraint; 
-};
-
-//=================================================================================================
-/// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency
-/// remove only if there is a better solution
-/// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with
-/// forward declarations
-inline void increment( const class Expr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class Expr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class ApplicationExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class ApplicationExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class UntypedExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class UntypedExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class NameExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class NameExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class AddressExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class AddressExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class LabelAddressExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class LabelAddressExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class CastExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class CastExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class KeywordCastExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class KeywordCastExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class VirtualCastExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class VirtualCastExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class MemberExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class MemberExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class UntypedMemberExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class UntypedMemberExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class VariableExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class VariableExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class ConstantExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class ConstantExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class SizeofExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class SizeofExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class AlignofExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class AlignofExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class UntypedOffsetofExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class UntypedOffsetofExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class OffsetofExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class OffsetofExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class OffsetPackExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class OffsetPackExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class LogicalExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class LogicalExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class ConditionalExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class ConditionalExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class CommaExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class CommaExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class TypeExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class TypeExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class AsmExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class AsmExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-// inline void increment( const class ImplicitCopyCtorExpr * node, Node::ref_type ref ) { node->increment(ref); }
-// inline void decrement( const class ImplicitCopyCtorExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-// inline void increment( const class ConstructorExpr * node, Node::ref_type ref ) { node->increment(ref); }
-// inline void decrement( const class ConstructorExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-// inline void increment( const class CompoundLiteralExpr * node, Node::ref_type ref ) { node->increment(ref); }
-// inline void decrement( const class CompoundLiteralExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-// inline void increment( const class UntypedValofExpr * node, Node::ref_type ref ) { node->increment(ref); }
-// inline void decrement( const class UntypedValofExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-// inline void increment( const class RangeExpr * node, Node::ref_type ref ) { node->increment(ref); }
-// inline void decrement( const class RangeExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-// inline void increment( const class UntypedTupleExpr * node, Node::ref_type ref ) { node->increment(ref); }
-// inline void decrement( const class UntypedTupleExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-// inline void increment( const class TupleExpr * node, Node::ref_type ref ) { node->increment(ref); }
-// inline void decrement( const class TupleExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-// inline void increment( const class TupleIndexExpr * node, Node::ref_type ref ) { node->increment(ref); }
-// inline void decrement( const class TupleIndexExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-// inline void increment( const class TupleAssignExpr * node, Node::ref_type ref ) { node->increment(ref); }
-// inline void decrement( const class TupleAssignExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-// inline void increment( const class StmtExpr * node, Node::ref_type ref ) { node->increment(ref); }
-// inline void decrement( const class StmtExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-// inline void increment( const class UniqueExpr * node, Node::ref_type ref ) { node->increment(ref); }
-// inline void decrement( const class UniqueExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-// inline void increment( const class UntypedInitExpr * node, Node::ref_type ref ) { node->increment(ref); }
-// inline void decrement( const class UntypedInitExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-// inline void increment( const class InitExpr * node, Node::ref_type ref ) { node->increment(ref); }
-// inline void decrement( const class InitExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-// inline void increment( const class DeletedExpr * node, Node::ref_type ref ) { node->increment(ref); }
-// inline void decrement( const class DeletedExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-// inline void increment( const class DefaultArgExpr * node, Node::ref_type ref ) { node->increment(ref); }
-// inline void decrement( const class DefaultArgExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-// inline void increment( const class GenericExpr * node, Node::ref_type ref ) { node->increment(ref); }
-// inline void decrement( const class GenericExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+	ptr<Expr> constraint;
+};
+
 }
 
Index: src/AST/Fwd.hpp
===================================================================
--- src/AST/Fwd.hpp	(revision 1fb7bfd9039e83e68b46670a2664f5a59ccf6cbc)
+++ src/AST/Fwd.hpp	(revision 87701b607d65c7537ed3e6026229861ab1667c6b)
@@ -136,218 +136,4 @@
 std::string toString( const Node * );
 
-//=================================================================================================
-/// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency
-/// remove only if there is a better solution
-/// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with
-/// forward declarations
-inline void decrement( const class Node * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class Node * node, Node::ref_type ref ) { node->increment(ref); }
-inline void increment( const class ParseNode *, Node::ref_type );
-inline void decrement( const class ParseNode *, Node::ref_type );
-inline void increment( const class Decl *, Node::ref_type );
-inline void decrement( const class Decl *, Node::ref_type );
-inline void increment( const class DeclWithType *, Node::ref_type );
-inline void decrement( const class DeclWithType *, Node::ref_type );
-inline void increment( const class ObjectDecl *, Node::ref_type );
-inline void decrement( const class ObjectDecl *, Node::ref_type );
-inline void increment( const class FunctionDecl *, Node::ref_type );
-inline void decrement( const class FunctionDecl *, Node::ref_type );
-inline void increment( const class AggregateDecl *, Node::ref_type );
-inline void decrement( const class AggregateDecl *, Node::ref_type );
-inline void increment( const class StructDecl *, Node::ref_type );
-inline void decrement( const class StructDecl *, Node::ref_type );
-inline void increment( const class UnionDecl *, Node::ref_type );
-inline void decrement( const class UnionDecl *, Node::ref_type );
-inline void increment( const class EnumDecl *, Node::ref_type );
-inline void decrement( const class EnumDecl *, Node::ref_type );
-inline void increment( const class TraitDecl *, Node::ref_type );
-inline void decrement( const class TraitDecl *, Node::ref_type );
-inline void increment( const class NamedTypeDecl *, Node::ref_type );
-inline void decrement( const class NamedTypeDecl *, Node::ref_type );
-inline void increment( const class TypeDecl *, Node::ref_type );
-inline void decrement( const class TypeDecl *, Node::ref_type );
-inline void increment( const class TypedefDecl *, Node::ref_type );
-inline void decrement( const class TypedefDecl *, Node::ref_type );
-inline void increment( const class AsmDecl *, Node::ref_type );
-inline void decrement( const class AsmDecl *, Node::ref_type );
-inline void increment( const class StaticAssertDecl *, Node::ref_type );
-inline void decrement( const class StaticAssertDecl *, Node::ref_type );
-inline void increment( const class Stmt *, Node::ref_type );
-inline void decrement( const class Stmt *, Node::ref_type );
-inline void increment( const class CompoundStmt *, Node::ref_type );
-inline void decrement( const class CompoundStmt *, Node::ref_type );
-inline void increment( const class ExprStmt *, Node::ref_type );
-inline void decrement( const class ExprStmt *, Node::ref_type );
-inline void increment( const class AsmStmt *, Node::ref_type );
-inline void decrement( const class AsmStmt *, Node::ref_type );
-inline void increment( const class DirectiveStmt *, Node::ref_type );
-inline void decrement( const class DirectiveStmt *, Node::ref_type );
-inline void increment( const class IfStmt *, Node::ref_type );
-inline void decrement( const class IfStmt *, Node::ref_type );
-inline void increment( const class WhileStmt *, Node::ref_type );
-inline void decrement( const class WhileStmt *, Node::ref_type );
-inline void increment( const class ForStmt *, Node::ref_type );
-inline void decrement( const class ForStmt *, Node::ref_type );
-inline void increment( const class SwitchStmt *, Node::ref_type );
-inline void decrement( const class SwitchStmt *, Node::ref_type );
-inline void increment( const class CaseStmt *, Node::ref_type );
-inline void decrement( const class CaseStmt *, Node::ref_type );
-inline void increment( const class BranchStmt *, Node::ref_type );
-inline void decrement( const class BranchStmt *, Node::ref_type );
-inline void increment( const class ReturnStmt *, Node::ref_type );
-inline void decrement( const class ReturnStmt *, Node::ref_type );
-inline void increment( const class ThrowStmt *, Node::ref_type );
-inline void decrement( const class ThrowStmt *, Node::ref_type );
-inline void increment( const class TryStmt *, Node::ref_type );
-inline void decrement( const class TryStmt *, Node::ref_type );
-inline void increment( const class CatchStmt *, Node::ref_type );
-inline void decrement( const class CatchStmt *, Node::ref_type );
-inline void increment( const class FinallyStmt *, Node::ref_type );
-inline void decrement( const class FinallyStmt *, Node::ref_type );
-inline void increment( const class WaitForStmt *, Node::ref_type );
-inline void decrement( const class WaitForStmt *, Node::ref_type );
-inline void increment( const class WithStmt *, Node::ref_type );
-inline void decrement( const class WithStmt *, Node::ref_type );
-inline void increment( const class DeclStmt *, Node::ref_type );
-inline void decrement( const class DeclStmt *, Node::ref_type );
-inline void increment( const class NullStmt *, Node::ref_type );
-inline void decrement( const class NullStmt *, Node::ref_type );
-inline void increment( const class ImplicitCtorDtorStmt *, Node::ref_type );
-inline void decrement( const class ImplicitCtorDtorStmt *, Node::ref_type );
-inline void increment( const class Expr *, Node::ref_type );
-inline void decrement( const class Expr *, Node::ref_type );
-inline void increment( const class ApplicationExpr *, Node::ref_type );
-inline void decrement( const class ApplicationExpr *, Node::ref_type );
-inline void increment( const class UntypedExpr *, Node::ref_type );
-inline void decrement( const class UntypedExpr *, Node::ref_type );
-inline void increment( const class NameExpr *, Node::ref_type );
-inline void decrement( const class NameExpr *, Node::ref_type );
-inline void increment( const class AddressExpr *, Node::ref_type );
-inline void decrement( const class AddressExpr *, Node::ref_type );
-inline void increment( const class LabelAddressExpr *, Node::ref_type );
-inline void decrement( const class LabelAddressExpr *, Node::ref_type );
-inline void increment( const class CastExpr *, Node::ref_type );
-inline void decrement( const class CastExpr *, Node::ref_type );
-inline void increment( const class KeywordCastExpr *, Node::ref_type );
-inline void decrement( const class KeywordCastExpr *, Node::ref_type );
-inline void increment( const class VirtualCastExpr *, Node::ref_type );
-inline void decrement( const class VirtualCastExpr *, Node::ref_type );
-inline void increment( const class MemberExpr *, Node::ref_type );
-inline void decrement( const class MemberExpr *, Node::ref_type );
-inline void increment( const class UntypedMemberExpr *, Node::ref_type );
-inline void decrement( const class UntypedMemberExpr *, Node::ref_type );
-inline void increment( const class VariableExpr *, Node::ref_type );
-inline void decrement( const class VariableExpr *, Node::ref_type );
-inline void increment( const class ConstantExpr *, Node::ref_type );
-inline void decrement( const class ConstantExpr *, Node::ref_type );
-inline void increment( const class SizeofExpr *, Node::ref_type );
-inline void decrement( const class SizeofExpr *, Node::ref_type );
-inline void increment( const class AlignofExpr *, Node::ref_type );
-inline void decrement( const class AlignofExpr *, Node::ref_type );
-inline void increment( const class UntypedOffsetofExpr *, Node::ref_type );
-inline void decrement( const class UntypedOffsetofExpr *, Node::ref_type );
-inline void increment( const class OffsetofExpr *, Node::ref_type );
-inline void decrement( const class OffsetofExpr *, Node::ref_type );
-inline void increment( const class OffsetPackExpr *, Node::ref_type );
-inline void decrement( const class OffsetPackExpr *, Node::ref_type );
-inline void increment( const class LogicalExpr *, Node::ref_type );
-inline void decrement( const class LogicalExpr *, Node::ref_type );
-inline void increment( const class ConditionalExpr *, Node::ref_type );
-inline void decrement( const class ConditionalExpr *, Node::ref_type );
-inline void increment( const class CommaExpr *, Node::ref_type );
-inline void decrement( const class CommaExpr *, Node::ref_type );
-inline void increment( const class TypeExpr *, Node::ref_type );
-inline void decrement( const class TypeExpr *, Node::ref_type );
-inline void increment( const class AsmExpr *, Node::ref_type );
-inline void decrement( const class AsmExpr *, Node::ref_type );
-inline void increment( const class ImplicitCopyCtorExpr *, Node::ref_type );
-inline void decrement( const class ImplicitCopyCtorExpr *, Node::ref_type );
-inline void increment( const class ConstructorExpr *, Node::ref_type );
-inline void decrement( const class ConstructorExpr *, Node::ref_type );
-inline void increment( const class CompoundLiteralExpr *, Node::ref_type );
-inline void decrement( const class CompoundLiteralExpr *, Node::ref_type );
-inline void increment( const class UntypedValofExpr *, Node::ref_type );
-inline void decrement( const class UntypedValofExpr *, Node::ref_type );
-inline void increment( const class RangeExpr *, Node::ref_type );
-inline void decrement( const class RangeExpr *, Node::ref_type );
-inline void increment( const class UntypedTupleExpr *, Node::ref_type );
-inline void decrement( const class UntypedTupleExpr *, Node::ref_type );
-inline void increment( const class TupleExpr *, Node::ref_type );
-inline void decrement( const class TupleExpr *, Node::ref_type );
-inline void increment( const class TupleIndexExpr *, Node::ref_type );
-inline void decrement( const class TupleIndexExpr *, Node::ref_type );
-inline void increment( const class TupleAssignExpr *, Node::ref_type );
-inline void decrement( const class TupleAssignExpr *, Node::ref_type );
-inline void increment( const class StmtExpr *, Node::ref_type );
-inline void decrement( const class StmtExpr *, Node::ref_type );
-inline void increment( const class UniqueExpr *, Node::ref_type );
-inline void decrement( const class UniqueExpr *, Node::ref_type );
-inline void increment( const class UntypedInitExpr *, Node::ref_type );
-inline void decrement( const class UntypedInitExpr *, Node::ref_type );
-inline void increment( const class InitExpr *, Node::ref_type );
-inline void decrement( const class InitExpr *, Node::ref_type );
-inline void increment( const class DeletedExpr *, Node::ref_type );
-inline void decrement( const class DeletedExpr *, Node::ref_type );
-inline void increment( const class DefaultArgExpr *, Node::ref_type );
-inline void decrement( const class DefaultArgExpr *, Node::ref_type );
-inline void increment( const class GenericExpr *, Node::ref_type );
-inline void decrement( const class GenericExpr *, Node::ref_type );
-inline void increment( const class Type *, Node::ref_type );
-inline void decrement( const class Type *, Node::ref_type );
-inline void increment( const class VoidType *, Node::ref_type );
-inline void decrement( const class VoidType *, Node::ref_type );
-inline void increment( const class BasicType *, Node::ref_type );
-inline void decrement( const class BasicType *, Node::ref_type );
-inline void increment( const class PointerType *, Node::ref_type );
-inline void decrement( const class PointerType *, Node::ref_type );
-inline void increment( const class ArrayType *, Node::ref_type );
-inline void decrement( const class ArrayType *, Node::ref_type );
-inline void increment( const class ReferenceType *, Node::ref_type );
-inline void decrement( const class ReferenceType *, Node::ref_type );
-inline void increment( const class QualifiedType *, Node::ref_type );
-inline void decrement( const class QualifiedType *, Node::ref_type );
-inline void increment( const class FunctionType *, Node::ref_type );
-inline void decrement( const class FunctionType *, Node::ref_type );
-inline void increment( const class ReferenceToType *, Node::ref_type );
-inline void decrement( const class ReferenceToType *, Node::ref_type );
-inline void increment( const class StructInstType *, Node::ref_type );
-inline void decrement( const class StructInstType *, Node::ref_type );
-inline void increment( const class UnionInstType *, Node::ref_type );
-inline void decrement( const class UnionInstType *, Node::ref_type );
-inline void increment( const class EnumInstType *, Node::ref_type );
-inline void decrement( const class EnumInstType *, Node::ref_type );
-inline void increment( const class TraitInstType *, Node::ref_type );
-inline void decrement( const class TraitInstType *, Node::ref_type );
-inline void increment( const class TypeInstType *, Node::ref_type );
-inline void decrement( const class TypeInstType *, Node::ref_type );
-inline void increment( const class TupleType *, Node::ref_type );
-inline void decrement( const class TupleType *, Node::ref_type );
-inline void increment( const class TypeofType *, Node::ref_type );
-inline void decrement( const class TypeofType *, Node::ref_type );
-inline void increment( const class VarArgsType *, Node::ref_type );
-inline void decrement( const class VarArgsType *, Node::ref_type );
-inline void increment( const class ZeroType *, Node::ref_type );
-inline void decrement( const class ZeroType *, Node::ref_type );
-inline void increment( const class OneType *, Node::ref_type );
-inline void decrement( const class OneType *, Node::ref_type );
-inline void increment( const class GlobalScopeType *, Node::ref_type );
-inline void decrement( const class GlobalScopeType *, Node::ref_type );
-inline void increment( const class Designation *, Node::ref_type );
-inline void decrement( const class Designation *, Node::ref_type );
-inline void increment( const class Init *, Node::ref_type );
-inline void decrement( const class Init *, Node::ref_type );
-inline void increment( const class SingleInit *, Node::ref_type );
-inline void decrement( const class SingleInit *, Node::ref_type );
-inline void increment( const class ListInit *, Node::ref_type );
-inline void decrement( const class ListInit *, Node::ref_type );
-inline void increment( const class ConstructorInit *, Node::ref_type );
-inline void decrement( const class ConstructorInit *, Node::ref_type );
-inline void increment( const class Constant *, Node::ref_type );
-inline void decrement( const class Constant *, Node::ref_type );
-inline void increment( const class Attribute *, Node::ref_type );
-inline void decrement( const class Attribute *, Node::ref_type );
-inline void increment( const class TypeSubstitution *, Node::ref_type );
-inline void decrement( const class TypeSubstitution *, Node::ref_type );
-
 typedef unsigned int UniqueId;
 
Index: src/AST/Init.cpp
===================================================================
--- src/AST/Init.cpp	(revision 1fb7bfd9039e83e68b46670a2664f5a59ccf6cbc)
+++ src/AST/Init.cpp	(revision 87701b607d65c7537ed3e6026229861ab1667c6b)
@@ -22,8 +22,8 @@
 namespace ast {
 
-ListInit::ListInit( const CodeLocation& loc, std::vector<ptr<Init>>&& is, 
-	std::vector<ptr<Designation>>&& ds, bool mc)
+ListInit::ListInit( const CodeLocation& loc, std::vector<ptr<Init>>&& is,
+	std::vector<ptr<Designation>>&& ds, ConstructFlag mc)
 : Init( loc, mc ), initializers( std::move(is) ), designations( std::move(ds) ) {
-	// handle common case where ListInit is created without designations by making an 
+	// handle common case where ListInit is created without designations by making an
 	// equivalent-length empty list
 	if ( designations.empty() ) {
@@ -32,5 +32,5 @@
 		}
 	}
-	
+
 	assertf( initializers.size() == designations.size(), "Created ListInit with mismatching "
 		"initializers (%zd) and designations (%zd)", initializers.size(), designations.size() );
Index: src/AST/Init.hpp
===================================================================
--- src/AST/Init.hpp	(revision 1fb7bfd9039e83e68b46670a2664f5a59ccf6cbc)
+++ src/AST/Init.hpp	(revision 87701b607d65c7537ed3e6026229861ab1667c6b)
@@ -54,5 +54,5 @@
 	const Init * accept( Visitor& v ) const override = 0;
 private:
-	const Init * clone() const override = 0;
+	Init * clone() const override = 0;
 };
 
@@ -72,5 +72,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
@@ -100,5 +100,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
@@ -123,21 +123,7 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
-
-//=================================================================================================
-/// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency
-/// remove only if there is a better solution
-/// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with
-/// forward declarations
-inline void increment( const class Init * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class Init * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class SingleInit * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class SingleInit * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class ListInit * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ListInit * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class ConstructorInit * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ConstructorInit * node, Node::ref_type ref ) { node->decrement( ref ); }
 }
 
Index: src/AST/LinkageSpec.cpp
===================================================================
--- src/AST/LinkageSpec.cpp	(revision 1fb7bfd9039e83e68b46670a2664f5a59ccf6cbc)
+++ src/AST/LinkageSpec.cpp	(revision 87701b607d65c7537ed3e6026229861ab1667c6b)
@@ -43,12 +43,12 @@
 
 	std::string name( Spec spec ) {
-		switch ( spec ) {
-		case Intrinsic:  return "intrinsic";
-		case C:          return "C";
-		case Cforall:    return "Cforall";
-		case AutoGen:    return "autogenerated cfa";
-		case Compiler:   return "compiler built-in";
-		case BuiltinCFA: return "cfa built-in";
-		case BuiltinC:   return "c built-in";
+		switch ( spec.val ) {
+		case Intrinsic.val:  return "intrinsic";
+		case C.val:          return "C";
+		case Cforall.val:    return "Cforall";
+		case AutoGen.val:    return "autogenerated cfa";
+		case Compiler.val:   return "compiler built-in";
+		case BuiltinCFA.val: return "cfa built-in";
+		case BuiltinC.val:   return "c built-in";
 		default:         return "<unnamed linkage spec>";
 		}
Index: src/AST/Node.cpp
===================================================================
--- src/AST/Node.cpp	(revision 87701b607d65c7537ed3e6026229861ab1667c6b)
+++ src/AST/Node.cpp	(revision 87701b607d65c7537ed3e6026229861ab1667c6b)
@@ -0,0 +1,236 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// Node.hpp --
+//
+// Author           : Thierry Delisle
+// Created On       : Thu May 16 14:16:00 2019
+// Last Modified By :
+// Last Modified On :
+// Update Count     :
+//
+
+#include "Node.hpp"
+#include "Fwd.hpp"
+#include "Decl.hpp"
+#include "Expr.hpp"
+#include "Stmt.hpp"
+#include "Type.hpp"
+
+template< typename node_t, enum ast::Node::ref_type ref_t >
+void ast::ptr_base<node_t, ref_t>::_inc( const node_t * node ) { node->increment(ref_t); }
+
+template< typename node_t, enum ast::Node::ref_type ref_t >
+void ast::ptr_base<node_t, ref_t>::_dec( const node_t * node ) { node->decrement(ref_t); }
+
+template class ast::ptr_base< ast::Node, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::Node, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ParseNode, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ParseNode, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::Decl, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::Decl, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::DeclWithType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::DeclWithType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ObjectDecl, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ObjectDecl, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::FunctionDecl, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::FunctionDecl, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::AggregateDecl, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::AggregateDecl, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::StructDecl, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::StructDecl, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::UnionDecl, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::UnionDecl, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::EnumDecl, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::EnumDecl, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::TraitDecl, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::TraitDecl, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::NamedTypeDecl, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::NamedTypeDecl, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::TypeDecl, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::TypeDecl, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::TypedefDecl, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::TypedefDecl, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::AsmDecl, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::AsmDecl, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::StaticAssertDecl, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::StaticAssertDecl, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::Stmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::Stmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::CompoundStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::CompoundStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ExprStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ExprStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::AsmStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::AsmStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::DirectiveStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::DirectiveStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::IfStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::IfStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::WhileStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::WhileStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ForStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ForStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::SwitchStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::SwitchStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::CaseStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::CaseStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::BranchStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::BranchStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ReturnStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ReturnStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ThrowStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ThrowStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::TryStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::TryStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::CatchStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::CatchStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::FinallyStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::FinallyStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::WaitForStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::WaitForStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::WithStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::WithStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::DeclStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::DeclStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::NullStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::NullStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ImplicitCtorDtorStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ImplicitCtorDtorStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::Expr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::Expr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ApplicationExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ApplicationExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::UntypedExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::UntypedExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::NameExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::NameExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::AddressExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::AddressExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::LabelAddressExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::LabelAddressExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::CastExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::CastExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::KeywordCastExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::KeywordCastExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::VirtualCastExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::VirtualCastExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::MemberExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::MemberExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::UntypedMemberExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::UntypedMemberExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::VariableExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::VariableExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ConstantExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ConstantExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::SizeofExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::SizeofExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::AlignofExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::AlignofExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::UntypedOffsetofExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::UntypedOffsetofExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::OffsetofExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::OffsetofExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::OffsetPackExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::OffsetPackExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::LogicalExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::LogicalExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ConditionalExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ConditionalExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::CommaExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::CommaExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::TypeExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::TypeExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::AsmExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::AsmExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ImplicitCopyCtorExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ImplicitCopyCtorExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ConstructorExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ConstructorExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::CompoundLiteralExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::CompoundLiteralExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::UntypedValofExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::UntypedValofExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::RangeExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::RangeExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::UntypedTupleExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::UntypedTupleExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::TupleExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::TupleExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::TupleIndexExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::TupleIndexExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::TupleAssignExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::TupleAssignExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::StmtExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::StmtExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::UniqueExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::UniqueExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::UntypedInitExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::UntypedInitExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::InitExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::InitExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::DeletedExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::DeletedExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::DefaultArgExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::DefaultArgExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::GenericExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::GenericExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::Type, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::Type, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::VoidType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::VoidType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::BasicType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::BasicType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::PointerType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::PointerType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ArrayType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ArrayType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ReferenceType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ReferenceType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::QualifiedType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::QualifiedType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::FunctionType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::FunctionType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ReferenceToType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ReferenceToType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::StructInstType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::StructInstType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::UnionInstType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::UnionInstType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::EnumInstType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::EnumInstType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::TraitInstType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::TraitInstType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::TypeInstType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::TypeInstType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::TupleType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::TupleType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::TypeofType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::TypeofType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::VarArgsType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::VarArgsType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ZeroType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ZeroType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::OneType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::OneType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::GlobalScopeType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::GlobalScopeType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::Designation, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::Designation, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::Init, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::Init, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::SingleInit, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::SingleInit, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ListInit, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ListInit, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ConstructorInit, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ConstructorInit, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::Constant, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::Constant, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::Attribute, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::Attribute, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::TypeSubstitution, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::TypeSubstitution, ast::Node::ref_type::strong >;
Index: src/AST/Node.hpp
===================================================================
--- src/AST/Node.hpp	(revision 1fb7bfd9039e83e68b46670a2664f5a59ccf6cbc)
+++ src/AST/Node.hpp	(revision 87701b607d65c7537ed3e6026229861ab1667c6b)
@@ -44,5 +44,16 @@
 	};
 
-	inline void increment(ref_type ref) const {
+private:
+	/// Make a copy of this node; should be overridden in subclass with more precise return type
+	virtual Node * clone() const = 0;
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend node_t * mutate(const node_t * node);
+
+	mutable size_t strong_count = 0;
+	mutable size_t weak_count = 0;
+
+	void increment(ref_type ref) const {
 		switch (ref) {
 			case ref_type::strong: strong_count++; break;
@@ -51,5 +62,5 @@
 	}
 
-	inline void decrement(ref_type ref) const {
+	void decrement(ast::Node::ref_type ref) const {
 		switch (ref) {
 			case ref_type::strong: strong_count--; break;
@@ -61,14 +72,7 @@
 		}
 	}
-private:
-	/// Make a copy of this node; should be overridden in subclass with more precise return type
-	virtual const Node * clone() const = 0;
 
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
-
-	mutable size_t strong_count = 0;
-	mutable size_t weak_count = 0;
+	template< typename node_t, enum Node::ref_type ref_t >
+	friend class ptr_base;
 };
 
@@ -76,10 +80,6 @@
 // problems and be able to use auto return
 template<typename node_t>
-auto mutate( const node_t * node ) {
-	assertf(
-		node->strong_count >= 1,
-		"Error: attempting to mutate a node that appears to have been linked"
-	);
-	if (node->strong_count == 1) {
+node_t * mutate( const node_t * node ) {
+	if (node->strong_count <= 1) {
 		return const_cast<node_t *>(node);
 	}
@@ -100,15 +100,15 @@
 public:
 	ptr_base() : node(nullptr) {}
-	ptr_base( const node_t * n ) : node(n) { if( node ) increment(node, ref_t); }
-	~ptr_base() { if( node ) decrement(node, ref_t); }
+	ptr_base( const node_t * n ) : node(n) { if( node ) _inc(node); }
+	~ptr_base() { if( node ) _dec(node); }
 
 	template< enum Node::ref_type o_ref_t >
 	ptr_base( const ptr_base<node_t, o_ref_t> & o ) : node(o.node) {
-		if( node ) increment(node, ref_t);
+		if( node ) _inc(node);
 	}
 
 	template< enum Node::ref_type o_ref_t >
 	ptr_base( ptr_base<node_t, o_ref_t> && o ) : node(o.node) {
-		if( node ) increment(node, ref_t);
+		if( node ) _inc(node);
 	}
 
@@ -147,5 +147,5 @@
 		assign( n );
 		// get mutable version of `n`
-		auto r = mutate( node ); 
+		auto r = mutate( node );
 		// re-assign mutable version in case `mutate()` produced a new pointer
 		assign( r );
@@ -157,8 +157,11 @@
 private:
 	void assign( const node_t * other ) {
-		if( other ) increment(other, ref_t);
-		if( node  ) decrement(node , ref_t);
+		if( other ) _inc(other);
+		if( node  ) _dec(node );
 		node = other;
 	}
+
+	void _inc( const node_t * other );
+	void _dec( const node_t * other );
 
 protected:
Index: src/AST/ParseNode.hpp
===================================================================
--- src/AST/ParseNode.hpp	(revision 1fb7bfd9039e83e68b46670a2664f5a59ccf6cbc)
+++ src/AST/ParseNode.hpp	(revision 87701b607d65c7537ed3e6026229861ab1667c6b)
@@ -34,14 +34,12 @@
 
 	ParseNode( const ParseNode& o ) = default;
+private:
+	ParseNode * clone() const override = 0;
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend node_t * mutate(const node_t * node);
 };
 
-
-//=================================================================================================
-/// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency
-/// remove only if there is a better solution
-/// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with
-/// forward declarations
-inline void increment( const class ParseNode * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ParseNode * node, Node::ref_type ref ) { node->decrement( ref ); }
 }
 
Index: src/AST/Pass.hpp
===================================================================
--- src/AST/Pass.hpp	(revision 1fb7bfd9039e83e68b46670a2664f5a59ccf6cbc)
+++ src/AST/Pass.hpp	(revision 87701b607d65c7537ed3e6026229861ab1667c6b)
@@ -133,5 +133,4 @@
 	const ast::Expr *             visit( const ast::OffsetofExpr         * ) override final;
 	const ast::Expr *             visit( const ast::OffsetPackExpr       * ) override final;
-	const ast::Expr *             visit( const ast::AttrExpr             * ) override final;
 	const ast::Expr *             visit( const ast::LogicalExpr          * ) override final;
 	const ast::Expr *             visit( const ast::ConditionalExpr      * ) override final;
Index: src/AST/Pass.impl.hpp
===================================================================
--- src/AST/Pass.impl.hpp	(revision 1fb7bfd9039e83e68b46670a2664f5a59ccf6cbc)
+++ src/AST/Pass.impl.hpp	(revision 87701b607d65c7537ed3e6026229861ab1667c6b)
@@ -462,6 +462,6 @@
 	VISIT({
 		guard_indexer guard { * this };
-		maybe_accept( node, &StructDecl::parameters );
-		maybe_accept( node, &StructDecl::members    );
+		maybe_accept( node, &StructDecl::params  );
+		maybe_accept( node, &StructDecl::members );
 	})
 
@@ -483,6 +483,6 @@
 	VISIT({
 		guard_indexer guard { * this };
-		maybe_accept( node, &UnionDecl::parameters );
-		maybe_accept( node, &UnionDecl::members    );
+		maybe_accept( node, &UnionDecl::params  );
+		maybe_accept( node, &UnionDecl::members );
 	})
 
@@ -502,6 +502,6 @@
 	VISIT(
 		// unlike structs, traits, and unions, enums inject their members into the global scope
-		maybe_accept( node, &EnumDecl::parameters );
-		maybe_accept( node, &EnumDecl::members    );
+		maybe_accept( node, &EnumDecl::params  );
+		maybe_accept( node, &EnumDecl::members );
 	)
 
@@ -517,6 +517,6 @@
 	VISIT({
 		guard_indexer guard { *this };
-		maybe_accept( node, &TraitDecl::parameters );
-		maybe_accept( node, &TraitDecl::members    );
+		maybe_accept( node, &TraitDecl::params  );
+		maybe_accept( node, &TraitDecl::members );
 	})
 
@@ -534,6 +534,6 @@
 	VISIT({
 		guard_indexer guard { *this };
-		maybe_accept( node, &TypeDecl::parameters );
-		maybe_accept( node, &TypeDecl::base       );
+		maybe_accept( node, &TypeDecl::params );
+		maybe_accept( node, &TypeDecl::base   );
 	})
 
@@ -563,6 +563,6 @@
 	VISIT({
 		guard_indexer guard { *this };
-		maybe_accept( node, &TypedefDecl::parameters );
-		maybe_accept( node, &TypedefDecl::base       );
+		maybe_accept( node, &TypedefDecl::params );
+		maybe_accept( node, &TypedefDecl::base   );
 	})
 
@@ -690,4 +690,82 @@
 
 	VISIT_END( Stmt, node );
+}
+
+//--------------------------------------------------------------------------
+// ForStmt
+template< typename pass_t >
+const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ForStmt * node ) {
+	VISIT_START( node );
+
+	VISIT({
+		// for statements introduce a level of scope (for the initialization)
+		guard_indexer guard { *this };
+		maybe_accept( node, &ForStmt::inits );
+		maybe_accept( node, &ForStmt::cond  );
+		maybe_accept( node, &ForStmt::inc   );
+		maybe_accept( node, &ForStmt::body  );
+	})
+
+	VISIT_END( Stmt, node );
+}
+
+//--------------------------------------------------------------------------
+// SwitchStmt
+template< typename pass_t >
+const ast::Stmt * ast::Pass< pass_t >::visit( const ast::SwitchStmt * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		maybe_accept( node, &SwitchStmt::cond  );
+		maybe_accept( node, &SwitchStmt::stmts );
+	)
+
+	VISIT_END( Stmt, node );
+}
+
+//--------------------------------------------------------------------------
+// CaseStmt
+template< typename pass_t >
+const ast::Stmt * ast::Pass< pass_t >::visit( const ast::CaseStmt * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		maybe_accept( node, &CaseStmt::cond  );
+		maybe_accept( node, &CaseStmt::stmts );
+	)
+
+	VISIT_END( Stmt, node );
+}
+
+//--------------------------------------------------------------------------
+// BranchStmt
+template< typename pass_t >
+const ast::Stmt * ast::Pass< pass_t >::visit( const ast::BranchStmt * node ) {
+	VISIT_START( node );
+	VISIT_END( Stmt, node );
+}
+
+//--------------------------------------------------------------------------
+// ReturnStmt
+template< typename pass_t >
+const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ReturnStmt * node ) {
+	VISIT_START( node );
+
+	maybe_accept( node, &ReturnStmt::expr );
+
+	VISIT_END( Stmt, node );
+}
+
+//--------------------------------------------------------------------------
+// ThrowStmt
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( ThrowStmt * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->expr, *this );
+	maybeAccept_impl( node->target, *this );
+
+	VISIT_END( node );
 }
 
Index: src/AST/Pass.proto.hpp
===================================================================
--- src/AST/Pass.proto.hpp	(revision 1fb7bfd9039e83e68b46670a2664f5a59ccf6cbc)
+++ src/AST/Pass.proto.hpp	(revision 87701b607d65c7537ed3e6026229861ab1667c6b)
@@ -247,5 +247,5 @@
 		static inline auto addStructFwd( pass_t & pass, int, const ast::StructDecl * decl ) -> decltype( pass.indexer.addStruct( decl ), void() ) {
 			ast::StructDecl * fwd = new ast::StructDecl( decl->location, decl->name );
-			fwd->parameters = decl->parameters;
+			fwd->params = decl->params;
 			pass.indexer.addStruct( fwd );
 		}
@@ -257,5 +257,5 @@
 		static inline auto addUnionFwd( pass_t & pass, int, const ast::UnionDecl * decl ) -> decltype( pass.indexer.addUnion( decl ), void() ) {
 			UnionDecl * fwd = new UnionDecl( decl->location, decl->name );
-			fwd->parameters = decl->parameters;
+			fwd->params = decl->params;
 			pass.indexer.addUnion( fwd );
 		}
Index: src/AST/Stmt.cpp
===================================================================
--- src/AST/Stmt.cpp	(revision 1fb7bfd9039e83e68b46670a2664f5a59ccf6cbc)
+++ src/AST/Stmt.cpp	(revision 87701b607d65c7537ed3e6026229861ab1667c6b)
@@ -26,5 +26,5 @@
 
 // --- BranchStmt
-BranchStmt( const CodeLocation& loc, Kind kind, Label target, std::vector<Label>&& labels )
+BranchStmt::BranchStmt( const CodeLocation& loc, Kind kind, Label target, std::vector<Label>&& labels )
 : Stmt(loc, std::move(labels)), originalTarget(target), target(target), kind(kind) {
 	// Make sure a syntax error hasn't slipped through.
@@ -34,5 +34,5 @@
 const char * BranchStmt::kindNames[] = {
     "Goto", "Break", "Continue", "FallThrough", "FallThroughDefault"
-}
+};
 
 }
Index: src/AST/Stmt.hpp
===================================================================
--- src/AST/Stmt.hpp	(revision 1fb7bfd9039e83e68b46670a2664f5a59ccf6cbc)
+++ src/AST/Stmt.hpp	(revision 87701b607d65c7537ed3e6026229861ab1667c6b)
@@ -65,5 +65,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
@@ -80,5 +80,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
@@ -96,5 +96,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
@@ -121,5 +121,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
@@ -138,5 +138,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
@@ -160,5 +160,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
@@ -178,5 +178,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
@@ -198,5 +198,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
@@ -219,5 +219,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
@@ -240,5 +240,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
@@ -268,5 +268,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 
 	static const char * kindNames[kindEnd];
@@ -286,5 +286,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
@@ -307,5 +307,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
@@ -327,5 +327,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
@@ -349,5 +349,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
@@ -366,5 +366,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
@@ -406,5 +406,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
@@ -424,5 +424,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
@@ -440,5 +440,5 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
@@ -457,54 +457,6 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
-};
-
-//=================================================================================================
-/// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency
-/// remove only if there is a better solution
-/// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with
-/// forward declarations
-inline void increment( const class Stmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class Stmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class CompoundStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class CompoundStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class ExprStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ExprStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class AsmStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class AsmStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class DirectiveStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class DirectiveStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class IfStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class IfStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class WhileStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class WhileStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class ForStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ForStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class SwitchStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class SwitchStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class CaseStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class CaseStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class BranchStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class BranchStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class ReturnStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ReturnStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class ThrowStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ThrowStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class TryStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class TryStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class CatchStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class CatchStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class FinallyStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class FinallyStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class WaitForStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class WaitForStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class WithStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class WithStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class DeclStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class DeclStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class NullStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class NullStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class ImplicitCtorDtorStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ImplicitCtorDtorStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+	friend node_t * mutate(const node_t * node);
+};
 
 }
Index: src/AST/Type.hpp
===================================================================
--- src/AST/Type.hpp	(revision 1fb7bfd9039e83e68b46670a2664f5a59ccf6cbc)
+++ src/AST/Type.hpp	(revision 87701b607d65c7537ed3e6026229861ab1667c6b)
@@ -34,5 +34,5 @@
 public:
 	CV::Qualifiers qualifiers;
-	
+
 	Type( CV::Qualifiers q = {} ) : qualifiers(q) {}
 
@@ -76,5 +76,5 @@
 public:
 	VoidType( CV::Qualifiers q = {} ) : Type( q ) {}
-	
+
 	unsigned size() const override { return 0; }
 	bool isVoid() const override { return true; }
@@ -165,5 +165,5 @@
 
 	PointerType( const Type * b, CV::Qualifiers q = {} ) : Type(q), base(b), dimension() {}
-	PointerType( const Type * b, const Expr * d, LengthFlag vl, DimensionFlag s, 
+	PointerType( const Type * b, const Expr * d, LengthFlag vl, DimensionFlag s,
 		CV::Qualifiers q = {} ) : Type(q), base(b), dimension(d), isVarLen(vl), isStatic(s) {}
 
@@ -186,5 +186,5 @@
 	DimensionFlag isStatic;
 
-	ArrayType( const Type * b, const Expr * d, LengthFlag vl, DimensionFlag s, 
+	ArrayType( const Type * b, const Expr * d, LengthFlag vl, DimensionFlag s,
 		CV::Qualifiers q = {} ) : Type(q), base(b), dimension(d), isVarLen(vl), isStatic(s) {}
 
@@ -224,5 +224,5 @@
 	ptr<Type> child;
 
-	QualifiedType( const Type * p, const Type * c, CV::Qualifiers q = {} ) 
+	QualifiedType( const Type * p, const Type * c, CV::Qualifiers q = {} )
 	: Type(q), parent(p), child(c) {}
 
@@ -239,5 +239,5 @@
 	ForallList forall;
 
-	ParameterizedType( ForallList&& fs = {}, CV::Qualifiers q = {} ) 
+	ParameterizedType( ForallList&& fs = {}, CV::Qualifiers q = {} )
 	: Type(q), forall(std::move(fs)) {}
 	ParameterizedType( CV::Qualifiers q ) : Type(q), forall() {}
@@ -256,5 +256,5 @@
 	std::vector<ptr<DeclWithType>> params;
 
-	/// Does the function accept a variable number of arguments following the arguments specified 
+	/// Does the function accept a variable number of arguments following the arguments specified
 	/// in the parameters list.
 	/// This could be because of
@@ -284,5 +284,5 @@
 	bool hoistType = false;
 
-	ReferenceToType( const std::string& n, CV::Qualifiers q = {}, 
+	ReferenceToType( const std::string& n, CV::Qualifiers q = {},
 		std::vector<ptr<Attribute>> && as = {} )
 	: ParameterizedType(q), params(), attributes(std::move(as)), name(n) {}
@@ -306,10 +306,10 @@
 	readonly<StructDecl> base;
 
-	StructInstType( const std::string& n, CV::Qualifiers q = {}, 
+	StructInstType( const std::string& n, CV::Qualifiers q = {},
 		std::vector<ptr<Attribute>> && as = {} )
 	: ReferenceToType( n, q, std::move(as) ), base() {}
-	StructInstType( const StructDecl * b, CV::Qualifiers q = {}, 
+	StructInstType( const StructDecl * b, CV::Qualifiers q = {},
 		std::vector<ptr<Attribute>> && as = {} );
-	
+
 	bool isComplete() const override;
 
@@ -328,10 +328,10 @@
 	readonly<UnionDecl> base;
 
-	UnionInstType( const std::string& n, CV::Qualifiers q = {}, 
+	UnionInstType( const std::string& n, CV::Qualifiers q = {},
 		std::vector<ptr<Attribute>> && as = {} )
 	: ReferenceToType( n, q, std::move(as) ), base() {}
-	UnionInstType( const UnionDecl * b, CV::Qualifiers q = {}, 
+	UnionInstType( const UnionDecl * b, CV::Qualifiers q = {},
 		std::vector<ptr<Attribute>> && as = {} );
-	
+
 	bool isComplete() const override;
 
@@ -350,10 +350,10 @@
 	readonly<EnumDecl> base;
 
-	EnumInstType( const std::string& n, CV::Qualifiers q = {}, 
+	EnumInstType( const std::string& n, CV::Qualifiers q = {},
 		std::vector<ptr<Attribute>> && as = {} )
 	: ReferenceToType( n, q, std::move(as) ), base() {}
-	EnumInstType( const EnumDecl * b, CV::Qualifiers q = {}, 
+	EnumInstType( const EnumDecl * b, CV::Qualifiers q = {},
 		std::vector<ptr<Attribute>> && as = {} );
-	
+
 	bool isComplete() const override;
 
@@ -372,10 +372,10 @@
 	readonly<TraitDecl> base;
 
-	TraitInstType( const std::string& n, CV::Qualifiers q = {}, 
+	TraitInstType( const std::string& n, CV::Qualifiers q = {},
 		std::vector<ptr<Attribute>> && as = {} )
 	: ReferenceToType( n, q, std::move(as) ), base() {}
-	TraitInstType( const TraitDecl * b, CV::Qualifiers q = {}, 
+	TraitInstType( const TraitDecl * b, CV::Qualifiers q = {},
 		std::vector<ptr<Attribute>> && as = {} );
-	
+
 	// not meaningful for TraitInstType
 	bool isComplete() const override { assert(false); }
@@ -396,8 +396,8 @@
 	TypeVar::Kind kind;
 
-	TypeInstType( const std::string& n, const TypeDecl * b, CV::Qualifiers q = {}, 
+	TypeInstType( const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
 		std::vector<ptr<Attribute>> && as = {} )
 	: ReferenceToType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
-	TypeInstType( const std::string& n, TypeVar::Kind k, CV::Qualifiers q = {}, 
+	TypeInstType( const std::string& n, TypeVar::Kind k, CV::Qualifiers q = {},
 		std::vector<ptr<Attribute>> && as = {} )
 	: ReferenceToType( n, q, std::move(as) ), base(), kind( k ) {}
@@ -430,9 +430,9 @@
 	iterator begin() const { return types.begin(); }
 	iterator end() const { return types.end(); }
-	
+
 	unsigned size() const override { return types.size(); }
 
 	const Type * getComponent( unsigned i ) override {
-		assertf( i < size(), "TupleType::getComponent: index %d must be less than size %d", 
+		assertf( i < size(), "TupleType::getComponent: index %d must be less than size %d",
 			i, size() );
 		return *(begin()+i);
@@ -450,5 +450,5 @@
 	enum Kind { Typeof, Basetypeof } kind;
 
-	TypeofType( const Expr * e, Kind k = Typeof, CV::Qualifiers q = {} ) 
+	TypeofType( const Expr * e, Kind k = Typeof, CV::Qualifiers q = {} )
 	: Type(q), expr(e), kind(k) {}
 
@@ -462,5 +462,5 @@
 public:
 	VarArgsType( CV::Qualifiers q = {} ) : Type( q ) {}
-	
+
 	const Type * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
@@ -472,8 +472,8 @@
 public:
 	ZeroType( CV::Qualifiers q = {} ) : Type( q ) {}
-	
-	const Type * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
-	ZeroType * clone() const override { return new ZeroType{ *this }; }	
+
+	const Type * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	ZeroType * clone() const override { return new ZeroType{ *this }; }
 };
 
@@ -497,50 +497,4 @@
 	GlobalScopeType * clone() const override { return new GlobalScopeType{ *this }; }
 };
-
-//=================================================================================================
-/// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency
-/// remove only if there is a better solution.
-/// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with
-/// forward declarations
-inline void increment( const class Type * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class Type * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class VoidType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class VoidType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class BasicType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class BasicType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class PointerType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class PointerType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class ArrayType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ArrayType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class ReferenceType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ReferenceType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class QualifiedType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class QualifiedType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class FunctionType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class FunctionType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class ReferenceToType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ReferenceToType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class StructInstType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class StructInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class UnionInstType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class UnionInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class EnumInstType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class EnumInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class TraitInstType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class TraitInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class TypeInstType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class TypeInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class TupleType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class TupleType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class TypeofType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class TypeofType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class VarArgsType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class VarArgsType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class ZeroType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ZeroType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class OneType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class OneType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class GlobalScopeType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class GlobalScopeType * node, Node::ref_type ref ) { node->decrement( ref ); }
 
 }
Index: src/AST/porting.md
===================================================================
--- src/AST/porting.md	(revision 1fb7bfd9039e83e68b46670a2664f5a59ccf6cbc)
+++ src/AST/porting.md	(revision 87701b607d65c7537ed3e6026229861ab1667c6b)
@@ -48,5 +48,5 @@
       /// Must be copied in ALL derived classes
       template<typename node_t>
-      friend auto mutate(const node_t * node);
+      friend node_t * mutate(const node_t * node);
 
 All leaves of the `Node` inheritance tree are now declared `final`
Index: src/Common/utility.h
===================================================================
--- src/Common/utility.h	(revision 1fb7bfd9039e83e68b46670a2664f5a59ccf6cbc)
+++ src/Common/utility.h	(revision 87701b607d65c7537ed3e6026229861ab1667c6b)
@@ -463,12 +463,18 @@
 std::pair<long long int, bool> eval(Expression * expr);
 
-// -----------------------------------------------------------------------------
-/// Reorders the input range in-place so that the minimal-value elements according to the 
-/// comparator are in front; 
+namespace ast {
+	class Expr;
+}
+
+std::pair<long long int, bool> eval(const ast::Expr * expr);
+
+// -----------------------------------------------------------------------------
+/// Reorders the input range in-place so that the minimal-value elements according to the
+/// comparator are in front;
 /// returns the iterator after the last minimal-value element.
 template<typename Iter, typename Compare>
 Iter sort_mins( Iter begin, Iter end, Compare& lt ) {
 	if ( begin == end ) return end;
-	
+
 	Iter min_pos = begin;
 	for ( Iter i = begin + 1; i != end; ++i ) {
