Index: src/AST/Convert.cpp
===================================================================
--- src/AST/Convert.cpp	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
+++ src/AST/Convert.cpp	(revision e67991fd01d5341ea7ee45736431dbe64851911e)
@@ -518,5 +518,5 @@
 	}
 
-	const ast::Stmt * visit( const ast::WithStmt * node ) override final {
+	const ast::Decl * visit( const ast::WithStmt * node ) override final {
 		if ( inCache( node ) ) return nullptr;
 		auto stmt = new WithStmt(
@@ -524,5 +524,6 @@
 			get<Statement>().accept1( node->stmt )
 		);
-		return stmtPostamble( stmt, node );
+		declPostamble( stmt, node );
+		return nullptr;
 	}
 
@@ -1039,6 +1040,6 @@
 				get<Expression>().accept1(node->expr),
 				inCache(node->deleteStmt) ?
-					this->node :
-					get<BaseSyntaxNode>().accept1(node->deleteStmt)
+					strict_dynamic_cast<Declaration*>(this->node) :
+					get<Declaration>().accept1(node->deleteStmt)
 			)
 		);
@@ -1908,6 +1909,5 @@
 			old->location,
 			GET_ACCEPT_V(exprs, Expr),
-			GET_ACCEPT_1(stmt, Stmt),
-			GET_LABELS_V(old->labels)
+			GET_ACCEPT_1(stmt, Stmt)
 		);
 		cache.emplace( old, this->node );
@@ -2397,6 +2397,6 @@
 				GET_ACCEPT_1(expr, Expr),
 				inCache(old->deleteStmt) ?
-					this->node :
-					GET_ACCEPT_1(deleteStmt, Node)
+					strict_dynamic_cast<ast::Decl*>(this->node) :
+					GET_ACCEPT_1(deleteStmt, Decl)
 			)
 		);
Index: src/AST/Decl.hpp
===================================================================
--- src/AST/Decl.hpp	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
+++ src/AST/Decl.hpp	(revision e67991fd01d5341ea7ee45736431dbe64851911e)
@@ -102,7 +102,7 @@
 	ptr<Expr> bitfieldWidth;
 
-	ObjectDecl( const CodeLocation & loc, const std::string & name, const Type * type, 
-		const Init * init = nullptr, Storage::Classes storage = {}, 
-		Linkage::Spec linkage = Linkage::C, const Expr * bitWd = nullptr, 
+	ObjectDecl( const CodeLocation & loc, const std::string & name, const Type * type,
+		const Init * init = nullptr, Storage::Classes storage = {},
+		Linkage::Spec linkage = Linkage::C, const Expr * bitWd = nullptr,
 		std::vector< ptr<Attribute> > && attrs = {}, Function::Specs fs = {} )
 	: DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), type( type ),
@@ -321,4 +321,19 @@
 };
 
+/// With statement `with (...) ...`
+class WithStmt final : public Decl {
+public:
+	std::vector<ptr<Expr>> exprs;
+	ptr<Stmt> stmt;
+
+	WithStmt( const CodeLocation & loc, std::vector<ptr<Expr>> && exprs, const Stmt * stmt )
+	: Decl(loc, "", Storage::Auto, Linkage::Cforall), exprs(std::move(exprs)), stmt(stmt) {}
+
+	const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	WithStmt * clone() const override { return new WithStmt{ *this }; }
+	MUTATE_FRIEND
+};
+
 class AsmDecl : public Decl {
 public:
Index: src/AST/Expr.hpp
===================================================================
--- src/AST/Expr.hpp	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
+++ src/AST/Expr.hpp	(revision e67991fd01d5341ea7ee45736431dbe64851911e)
@@ -769,7 +769,7 @@
 public:
 	ptr<Expr> expr;
-	readonly<Node> deleteStmt;
-
-	DeletedExpr( const CodeLocation & loc, const Expr * e, const Node * del )
+	readonly<Decl> deleteStmt;
+
+	DeletedExpr( const CodeLocation & loc, const Expr * e, const Decl * del )
 	: Expr( loc, e->result ), expr( e ), deleteStmt( del ) { assert( expr->result ); }
 
Index: src/AST/Pass.hpp
===================================================================
--- src/AST/Pass.hpp	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
+++ src/AST/Pass.hpp	(revision e67991fd01d5341ea7ee45736431dbe64851911e)
@@ -112,5 +112,5 @@
 	const ast::Stmt *             visit( const ast::FinallyStmt          * ) override final;
 	const ast::Stmt *             visit( const ast::WaitForStmt          * ) override final;
-	const ast::Stmt *             visit( const ast::WithStmt             * ) override final;
+	const ast::Decl *             visit( const ast::WithStmt             * ) override final;
 	const ast::NullStmt *         visit( const ast::NullStmt             * ) override final;
 	const ast::Stmt *             visit( const ast::DeclStmt             * ) override final;
Index: src/AST/Pass.impl.hpp
===================================================================
--- src/AST/Pass.impl.hpp	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
+++ src/AST/Pass.impl.hpp	(revision e67991fd01d5341ea7ee45736431dbe64851911e)
@@ -894,5 +894,5 @@
 // WithStmt
 template< typename pass_t >
-const ast::Stmt * ast::Pass< pass_t >::visit( const ast::WithStmt * node ) {
+const ast::Decl * ast::Pass< pass_t >::visit( const ast::WithStmt * node ) {
 	VISIT_START( node );
 
Index: src/AST/Print.cpp
===================================================================
--- src/AST/Print.cpp	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
+++ src/AST/Print.cpp	(revision e67991fd01d5341ea7ee45736431dbe64851911e)
@@ -37,5 +37,5 @@
 }
 
-class Printer : public Visitor {
+class Printer final : public Visitor {
 public:
 	ostream & os;
@@ -272,5 +272,5 @@
 
 public:
-	virtual const ast::DeclWithType * visit( const ast::ObjectDecl * node ) {
+	virtual const ast::DeclWithType * visit( const ast::ObjectDecl * node ) override final {
 		if ( ! node->name.empty() ) os << node->name << ": ";
 
@@ -314,5 +314,5 @@
 	}
 
-	virtual const ast::DeclWithType * visit( const ast::FunctionDecl * node ) {
+	virtual const ast::DeclWithType * visit( const ast::FunctionDecl * node ) override final {
 		if ( !node->name.empty() ) os << node->name << ": ";
 
@@ -342,25 +342,25 @@
 	}
 
-	virtual const ast::Decl * visit( const ast::StructDecl * node ) {
+	virtual const ast::Decl * visit( const ast::StructDecl * node ) override final {
 		print(node);
 		return node;
 	}
 
-	virtual const ast::Decl * visit( const ast::UnionDecl * node ) {
+	virtual const ast::Decl * visit( const ast::UnionDecl * node ) override final {
 		print(node);
 		return node;
 	}
 
-	virtual const ast::Decl * visit( const ast::EnumDecl * node ) {
+	virtual const ast::Decl * visit( const ast::EnumDecl * node ) override final {
 		print(node);
 		return node;
 	}
 
-	virtual const ast::Decl * visit( const ast::TraitDecl * node ) {
+	virtual const ast::Decl * visit( const ast::TraitDecl * node ) override final {
 		print(node);
 		return node;
 	}
 
-	virtual const ast::Decl * visit( const ast::TypeDecl * node ) {
+	virtual const ast::Decl * visit( const ast::TypeDecl * node ) override final {
 		preprint( node );
 		if ( ! short_mode && node->init ) {
@@ -374,15 +374,15 @@
 	}
 
-	virtual const ast::Decl * visit( const ast::TypedefDecl * node ) {
-		preprint( node );
-		return node;
-	}
-
-	virtual const ast::AsmDecl * visit( const ast::AsmDecl * node ) {
+	virtual const ast::Decl * visit( const ast::TypedefDecl * node ) override final {
+		preprint( node );
+		return node;
+	}
+
+	virtual const ast::AsmDecl * visit( const ast::AsmDecl * node ) override final {
 		safe_print( node->stmt );
 		return node;
 	}
 
-	virtual const ast::StaticAssertDecl * visit( const ast::StaticAssertDecl * node ) {
+	virtual const ast::StaticAssertDecl * visit( const ast::StaticAssertDecl * node ) override final {
 		os << "Static Assert with condition: ";
 		++indent;
@@ -396,5 +396,5 @@
 	}
 
-	virtual const ast::CompoundStmt * visit( const ast::CompoundStmt * node ) {
+	virtual const ast::CompoundStmt * visit( const ast::CompoundStmt * node ) override final {
 		os << "Compound Statement:" << endl;
 		++indent;
@@ -404,5 +404,5 @@
 	}
 
-	virtual const ast::Stmt * visit( const ast::ExprStmt * node ) {
+	virtual const ast::Stmt * visit( const ast::ExprStmt * node ) override final {
 		++indent;
 		os << "Expression Statement:" << endl << indent;
@@ -412,5 +412,5 @@
 	}
 
-	virtual const ast::Stmt * visit( const ast::AsmStmt * node ) {
+	virtual const ast::Stmt * visit( const ast::AsmStmt * node ) override final {
 		os << "Assembler Statement:" << endl;
 		++indent;
@@ -433,10 +433,10 @@
 	}
 
-	virtual const ast::Stmt * visit( const ast::DirectiveStmt * node ) {
+	virtual const ast::Stmt * visit( const ast::DirectiveStmt * node ) override final {
 		os << "GCC Directive: " << node->directive << endl;
 		return node;
 	}
 
-	virtual const ast::Stmt * visit( const ast::IfStmt * node ) {
+	virtual const ast::Stmt * visit( const ast::IfStmt * node ) override final {
 		os << "If on condition:" << endl;
 		++indent;
@@ -473,5 +473,5 @@
 	}
 
-	virtual const ast::Stmt * visit( const ast::WhileStmt * node ) {
+	virtual const ast::Stmt * visit( const ast::WhileStmt * node ) override final {
 		if ( node->isDoWhile ) { os << "Do-"; }
 		os << "While on condition:" << endl;
@@ -490,5 +490,5 @@
 	}
 
-	virtual const ast::Stmt * visit( const ast::ForStmt * node ) {
+	virtual const ast::Stmt * visit( const ast::ForStmt * node ) override final {
 		os << "For Statement" << endl;
 
@@ -532,5 +532,5 @@
 	}
 
-	virtual const ast::Stmt * visit( const ast::SwitchStmt * node ) {
+	virtual const ast::Stmt * visit( const ast::SwitchStmt * node ) override final {
 		os << "Switch on condition: ";
 		safe_print( node->cond );
@@ -546,5 +546,5 @@
 	}
 
-	virtual const ast::Stmt * visit( const ast::CaseStmt * node ) {
+	virtual const ast::Stmt * visit( const ast::CaseStmt * node ) override final {
 		if ( node->isDefault() ) {
 			os << indent << "Default ";
@@ -565,5 +565,5 @@
 	}
 
-	virtual const ast::Stmt * visit( const ast::BranchStmt * node ) {
+	virtual const ast::Stmt * visit( const ast::BranchStmt * node ) override final {
 		os << "Branch (" << node->kindName() << ")" << endl;
 		++indent;
@@ -586,5 +586,5 @@
 	}
 
-	virtual const ast::Stmt * visit( const ast::ReturnStmt * node ) {
+	virtual const ast::Stmt * visit( const ast::ReturnStmt * node ) override final {
 		os << "Return Statement, returning";
 		if ( node->expr ) {
@@ -601,5 +601,5 @@
 	}
 
-	virtual const ast::Stmt * visit( const ast::ThrowStmt * node ) {
+	virtual const ast::Stmt * visit( const ast::ThrowStmt * node ) override final {
 		if ( node->target ) os << "Non-Local ";
 
@@ -621,5 +621,5 @@
 	}
 
-	virtual const ast::Stmt * visit( const ast::TryStmt * node ) {
+	virtual const ast::Stmt * visit( const ast::TryStmt * node ) override final {
 		++indent;
 		os << "Try Statement" << endl << indent-1
@@ -642,5 +642,5 @@
 	}
 
-	virtual const ast::Stmt * visit( const ast::CatchStmt * node ) {
+	virtual const ast::Stmt * visit( const ast::CatchStmt * node ) override final {
 		os << "Catch ";
 		switch ( node->kind ) {
@@ -667,5 +667,5 @@
 	}
 
-	virtual const ast::Stmt * visit( const ast::FinallyStmt * node ) {
+	virtual const ast::Stmt * visit( const ast::FinallyStmt * node ) override final {
 		os << "Finally Statement" << endl;
 		os << indent << "... with block:" << endl;
@@ -678,5 +678,5 @@
 	}
 
-	virtual const ast::Stmt * visit( const ast::WaitForStmt * node ) {
+	virtual const ast::Stmt * visit( const ast::WaitForStmt * node ) override final {
 		os << "Waitfor Statement" << endl;
 		indent += 2;
@@ -732,5 +732,5 @@
 	}
 
-	virtual const ast::Stmt * visit( const ast::WithStmt * node ) {
+	virtual const ast::Decl * visit( const ast::WithStmt * node ) override final {
 		os << "With statement" << endl;
 		os << indent << "... with expressions:" << endl;
@@ -744,5 +744,5 @@
 	}
 
-	virtual const ast::NullStmt * visit( const ast::NullStmt * node ) {
+	virtual const ast::NullStmt * visit( const ast::NullStmt * node ) override final {
 		os << "Null Statement" << endl;
 		print( node->labels );
@@ -751,5 +751,5 @@
 	}
 
-	virtual const ast::Stmt * visit( const ast::DeclStmt * node ) {
+	virtual const ast::Stmt * visit( const ast::DeclStmt * node ) override final {
 		os << "Declaration of ";
 		safe_print( node->decl );
@@ -758,5 +758,5 @@
 	}
 
-	virtual const ast::Stmt * visit( const ast::ImplicitCtorDtorStmt * node ) {
+	virtual const ast::Stmt * visit( const ast::ImplicitCtorDtorStmt * node ) override final {
 		os << "Implicit Ctor Dtor Statement" << endl;
 		os << indent << "... with Ctor/Dtor: ";
@@ -769,5 +769,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::ApplicationExpr * node ) {
+	virtual const ast::Expr * visit( const ast::ApplicationExpr * node ) override final {
 		++indent;
 		os << "Application of" << endl << indent;
@@ -784,5 +784,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::UntypedExpr * node ) {
+	virtual const ast::Expr * visit( const ast::UntypedExpr * node ) override final {
 		++indent;
 		os << "Applying untyped:" << endl;
@@ -797,5 +797,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::NameExpr * node ) {
+	virtual const ast::Expr * visit( const ast::NameExpr * node ) override final {
 		os << "Name: " << node->name;
 		postprint( node );
@@ -804,5 +804,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::AddressExpr * node ) {
+	virtual const ast::Expr * visit( const ast::AddressExpr * node ) override final {
 		os << "Address of:" << endl;
 		++indent;
@@ -815,5 +815,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::LabelAddressExpr * node ) {
+	virtual const ast::Expr * visit( const ast::LabelAddressExpr * node ) override final {
 		os << "Address of label:" << node->arg;
 
@@ -821,5 +821,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::CastExpr * node ) {
+	virtual const ast::Expr * visit( const ast::CastExpr * node ) override final {
 		++indent;
 		os << (node->isGenerated ? "Generated" : "Explicit") << " cast of:" << endl << indent;
@@ -841,5 +841,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::KeywordCastExpr * node ) {
+	virtual const ast::Expr * visit( const ast::KeywordCastExpr * node ) override final {
 		++indent;
 		os << "Keyword Cast of:" << endl << indent;
@@ -852,5 +852,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::VirtualCastExpr * node ) {
+	virtual const ast::Expr * visit( const ast::VirtualCastExpr * node ) override final {
 		++indent;
 		os << "Virtual Cast of:" << endl << indent;
@@ -869,5 +869,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::UntypedMemberExpr * node ) {
+	virtual const ast::Expr * visit( const ast::UntypedMemberExpr * node ) override final {
 		++indent;
 		os << "Untyped Member Expression, with field: " << endl << indent;
@@ -881,5 +881,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::MemberExpr * node ) {
+	virtual const ast::Expr * visit( const ast::MemberExpr * node ) override final {
 		++indent;
 		os << "Member Expression, with field:" << endl << indent;
@@ -893,5 +893,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::VariableExpr * node ) {
+	virtual const ast::Expr * visit( const ast::VariableExpr * node ) override final {
 		os << "Variable Expression: ";
 		short_print( node->var );
@@ -901,5 +901,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::ConstantExpr * node ) {
+	virtual const ast::Expr * visit( const ast::ConstantExpr * node ) override final {
 		os << "Constant Expression (" << node->rep;
 		if ( node->result ) {
@@ -913,5 +913,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::SizeofExpr * node ) {
+	virtual const ast::Expr * visit( const ast::SizeofExpr * node ) override final {
 		os << "Sizeof Expression on: ";
 		++indent;
@@ -924,5 +924,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::AlignofExpr * node ) {
+	virtual const ast::Expr * visit( const ast::AlignofExpr * node ) override final {
 		os << "Alignof Expression on: ";
 		++indent;
@@ -935,5 +935,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::UntypedOffsetofExpr * node ) {
+	virtual const ast::Expr * visit( const ast::UntypedOffsetofExpr * node ) override final {
 		os << "Untyped Offsetof Expression on member " << node->member << " of ";
 		++indent;
@@ -945,5 +945,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::OffsetofExpr * node ) {
+	virtual const ast::Expr * visit( const ast::OffsetofExpr * node ) override final {
 		os << "Offsetof Expression on member " << node->member->name << " of ";
 		++indent;
@@ -955,5 +955,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::OffsetPackExpr * node ) {
+	virtual const ast::Expr * visit( const ast::OffsetPackExpr * node ) override final {
 		os << "Offset Pack Expression on: ";
 		++indent;
@@ -965,5 +965,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::LogicalExpr * node ) {
+	virtual const ast::Expr * visit( const ast::LogicalExpr * node ) override final {
 		os << "Short-circuited operation (" << (node->isAnd ? "and" : "or") << ") on: ";
 		safe_print( node->arg1 );
@@ -975,5 +975,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::ConditionalExpr * node ) {
+	virtual const ast::Expr * visit( const ast::ConditionalExpr * node ) override final {
 		++indent;
 		os << "Conditional expression on:" << endl << indent;
@@ -989,5 +989,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::CommaExpr * node ) {
+	virtual const ast::Expr * visit( const ast::CommaExpr * node ) override final {
 		++indent;
 		os << "Comma Expression:" << endl << indent;
@@ -1001,5 +1001,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::TypeExpr * node ) {
+	virtual const ast::Expr * visit( const ast::TypeExpr * node ) override final {
 		safe_print( node->type );
 		postprint( node );
@@ -1008,5 +1008,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::AsmExpr * node ) {
+	virtual const ast::Expr * visit( const ast::AsmExpr * node ) override final {
 		os << "Asm Expression:" << endl;
 		++indent;
@@ -1019,5 +1019,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::ImplicitCopyCtorExpr * node ) {
+	virtual const ast::Expr * visit( const ast::ImplicitCopyCtorExpr * node ) override final {
 		++indent;
 		os << "Implicit Copy Constructor Expression:" << endl << indent;
@@ -1029,5 +1029,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::ConstructorExpr * node ) {
+	virtual const ast::Expr * visit( const ast::ConstructorExpr * node ) override final {
 		os <<  "Constructor Expression:" << endl << indent+1;
 		indent += 2;
@@ -1039,5 +1039,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::CompoundLiteralExpr * node ) {
+	virtual const ast::Expr * visit( const ast::CompoundLiteralExpr * node ) override final {
 		++indent;
 		os << "Compound Literal Expression: " << endl << indent;
@@ -1051,5 +1051,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::RangeExpr * node ) {
+	virtual const ast::Expr * visit( const ast::RangeExpr * node ) override final {
 		os << "Range Expression: ";
 		safe_print( node->low );
@@ -1061,5 +1061,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::UntypedTupleExpr * node ) {
+	virtual const ast::Expr * visit( const ast::UntypedTupleExpr * node ) override final {
 		os << "Untyped Tuple:" << endl;
 		++indent;
@@ -1071,5 +1071,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::TupleExpr * node ) {
+	virtual const ast::Expr * visit( const ast::TupleExpr * node ) override final {
 		os << "Tuple:" << endl;
 		++indent;
@@ -1081,5 +1081,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::TupleIndexExpr * node ) {
+	virtual const ast::Expr * visit( const ast::TupleIndexExpr * node ) override final {
 		os << "Tuple Index Expression, with tuple:" << endl;
 		++indent;
@@ -1093,5 +1093,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::TupleAssignExpr * node ) {
+	virtual const ast::Expr * visit( const ast::TupleAssignExpr * node ) override final {
 		os << "Tuple Assignment Expression, with stmt expr:" << endl;
 		++indent;
@@ -1104,5 +1104,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::StmtExpr * node ) {
+	virtual const ast::Expr * visit( const ast::StmtExpr * node ) override final {
 		++indent;
 		os << "Statement Expression:" << endl << indent;
@@ -1122,5 +1122,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::UniqueExpr * node ) {
+	virtual const ast::Expr * visit( const ast::UniqueExpr * node ) override final {
 		++indent;
 		os << "Unique Expression with id: " << node->id << endl << indent;
@@ -1136,5 +1136,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::UntypedInitExpr * node ) {
+	virtual const ast::Expr * visit( const ast::UntypedInitExpr * node ) override final {
 		++indent;
 		os << "Untyped Init Expression" << endl << indent;
@@ -1152,5 +1152,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::InitExpr * node ) {
+	virtual const ast::Expr * visit( const ast::InitExpr * node ) override final {
 		++indent;
 		os << "Init Expression" << endl << indent;
@@ -1163,5 +1163,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::DeletedExpr * node ) {
+	virtual const ast::Expr * visit( const ast::DeletedExpr * node ) override final {
 		++indent;
 		os << "Deleted Expression" << endl << indent;
@@ -1174,5 +1174,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::DefaultArgExpr * node ) {
+	virtual const ast::Expr * visit( const ast::DefaultArgExpr * node ) override final {
 		++indent;
 		os << "Default Argument Expression" << endl << indent;
@@ -1183,5 +1183,5 @@
 	}
 
-	virtual const ast::Expr * visit( const ast::GenericExpr * node ) {
+	virtual const ast::Expr * visit( const ast::GenericExpr * node ) override final {
 		++indent;
 		os << "C11 _Generic Expression" << endl << indent;
@@ -1206,5 +1206,5 @@
 	}
 
-	virtual const ast::Type * visit( const ast::VoidType * node ) {
+	virtual const ast::Type * visit( const ast::VoidType * node ) override final {
 		preprint( node );
 		os << "void";
@@ -1212,5 +1212,5 @@
 	}
 
-	virtual const ast::Type * visit( const ast::BasicType * node ) {
+	virtual const ast::Type * visit( const ast::BasicType * node ) override final {
 		preprint( node );
 		os << ast::BasicType::typeNames[ node->kind ];
@@ -1218,5 +1218,5 @@
 	}
 
-	virtual const ast::Type * visit( const ast::PointerType * node ) {
+	virtual const ast::Type * visit( const ast::PointerType * node ) override final {
 		preprint( node );
 		if ( ! node->isArray() ) {
@@ -1241,5 +1241,5 @@
 	}
 
-	virtual const ast::Type * visit( const ast::ArrayType * node ) {
+	virtual const ast::Type * visit( const ast::ArrayType * node ) override final {
 		preprint( node );
 		if ( node->isStatic ) {
@@ -1265,5 +1265,5 @@
 	}
 
-	virtual const ast::Type * visit( const ast::ReferenceType * node ) {
+	virtual const ast::Type * visit( const ast::ReferenceType * node ) override final {
 		preprint( node );
 		os << "reference to ";
@@ -1273,5 +1273,5 @@
 	}
 
-	virtual const ast::Type * visit( const ast::QualifiedType * node ) {
+	virtual const ast::Type * visit( const ast::QualifiedType * node ) override final {
 		preprint( node );
 		++indent;
@@ -1286,5 +1286,5 @@
 	}
 
-	virtual const ast::Type * visit( const ast::FunctionType * node ) {
+	virtual const ast::Type * visit( const ast::FunctionType * node ) override final {
 		preprint( node );
 
@@ -1315,5 +1315,5 @@
 	}
 
-	virtual const ast::Type * visit( const ast::StructInstType * node ) {
+	virtual const ast::Type * visit( const ast::StructInstType * node ) override final {
 		preprint( node );
 		os << "instance of struct " << node->name;
@@ -1326,5 +1326,5 @@
 	}
 
-	virtual const ast::Type * visit( const ast::UnionInstType * node ) {
+	virtual const ast::Type * visit( const ast::UnionInstType * node ) override final {
 		preprint( node );
 		os << "instance of union " << node->name;
@@ -1337,5 +1337,5 @@
 	}
 
-	virtual const ast::Type * visit( const ast::EnumInstType * node ) {
+	virtual const ast::Type * visit( const ast::EnumInstType * node ) override final {
 		preprint( node );
 		os << "instance of enum " << node->name;
@@ -1348,5 +1348,5 @@
 	}
 
-	virtual const ast::Type * visit( const ast::TraitInstType * node ) {
+	virtual const ast::Type * visit( const ast::TraitInstType * node ) override final {
 		preprint( node );
 		os << "instance of trait " << node->name;
@@ -1356,5 +1356,5 @@
 	}
 
-	virtual const ast::Type * visit( const ast::TypeInstType * node ) {
+	virtual const ast::Type * visit( const ast::TypeInstType * node ) override final {
 		preprint( node );
 		os << "instance of type " << node->name
@@ -1365,5 +1365,5 @@
 	}
 
-	virtual const ast::Type * visit( const ast::TupleType * node ) {
+	virtual const ast::Type * visit( const ast::TupleType * node ) override final {
 		preprint( node );
 		os << "tuple of types" << endl;
@@ -1375,5 +1375,5 @@
 	}
 
-	virtual const ast::Type * visit( const ast::TypeofType * node ) {
+	virtual const ast::Type * visit( const ast::TypeofType * node ) override final {
 		preprint( node );
 		if ( node->kind == ast::TypeofType::Basetypeof ) { os << "base-"; }
@@ -1384,5 +1384,5 @@
 	}
 
-	virtual const ast::Type * visit( const ast::VarArgsType * node ) {
+	virtual const ast::Type * visit( const ast::VarArgsType * node ) override final {
 		preprint( node );
 		os << "builtin var args pack";
@@ -1390,5 +1390,5 @@
 	}
 
-	virtual const ast::Type * visit( const ast::ZeroType * node ) {
+	virtual const ast::Type * visit( const ast::ZeroType * node ) override final {
 		preprint( node );
 		os << "zero_t";
@@ -1396,5 +1396,5 @@
 	}
 
-	virtual const ast::Type * visit( const ast::OneType * node ) {
+	virtual const ast::Type * visit( const ast::OneType * node ) override final {
 		preprint( node );
 		os << "one_t";
@@ -1402,5 +1402,5 @@
 	}
 
-	virtual const ast::Type * visit( const ast::GlobalScopeType * node ) {
+	virtual const ast::Type * visit( const ast::GlobalScopeType * node ) override final {
 		preprint( node );
 		os << "Global Scope Type";
@@ -1408,5 +1408,5 @@
 	}
 
-	virtual const ast::Designation * visit( const ast::Designation * node ) {
+	virtual const ast::Designation * visit( const ast::Designation * node ) override final {
 		if ( node->designators.empty() ) return node;
 		os << "... designated by: " << endl;
@@ -1421,5 +1421,5 @@
 	}
 
-	virtual const ast::Init * visit( const ast::SingleInit * node ) {
+	virtual const ast::Init * visit( const ast::SingleInit * node ) override final {
 		os << "Simple Initializer: ";
 		safe_print( node->value );
@@ -1427,5 +1427,5 @@
 	}
 
-	virtual const ast::Init * visit( const ast::ListInit * node ) {
+	virtual const ast::Init * visit( const ast::ListInit * node ) override final {
 		os << "Compound initializer: " << endl;
 		++indent;
@@ -1445,5 +1445,5 @@
 	}
 
-	virtual const ast::Init * visit( const ast::ConstructorInit * node ) {
+	virtual const ast::Init * visit( const ast::ConstructorInit * node ) override final {
 		os << "Constructor initializer: " << endl;
 		if ( node->ctor ) {
@@ -1470,5 +1470,5 @@
 	}
 
-	virtual const ast::Attribute * visit( const ast::Attribute * node ) {
+	virtual const ast::Attribute * visit( const ast::Attribute * node ) override final {
 		if ( node->empty() ) return node;
 		os << "Attribute with name: " << node->name;
@@ -1481,5 +1481,5 @@
 	}
 
-	virtual const ast::TypeSubstitution * visit( const ast::TypeSubstitution * node ) {
+	virtual const ast::TypeSubstitution * visit( const ast::TypeSubstitution * node ) override final {
 		os << indent << "Types:" << endl;
 		for ( const auto& i : *node ) {
Index: src/AST/Stmt.hpp
===================================================================
--- src/AST/Stmt.hpp	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
+++ src/AST/Stmt.hpp	(revision e67991fd01d5341ea7ee45736431dbe64851911e)
@@ -380,20 +380,4 @@
 };
 
-/// With statement `with (...) ...`
-class WithStmt final : public Stmt {
-public:
-	std::vector<ptr<Expr>> exprs;
-	ptr<Stmt> stmt;
-
-	WithStmt( const CodeLocation & loc, std::vector<ptr<Expr>> && exprs, const Stmt * stmt,
-		std::vector<Label> && labels = {} )
-	: Stmt(loc, std::move(labels)), exprs(std::move(exprs)), stmt(stmt) {}
-
-	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
-	WithStmt * clone() const override { return new WithStmt{ *this }; }
-	MUTATE_FRIEND
-};
-
 /// Any declaration in a (compound) statement.
 class DeclStmt final : public Stmt {
Index: src/AST/SymbolTable.cpp
===================================================================
--- src/AST/SymbolTable.cpp	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
+++ src/AST/SymbolTable.cpp	(revision e67991fd01d5341ea7ee45736431dbe64851911e)
@@ -73,5 +73,5 @@
 
 SymbolTable::SymbolTable()
-: idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable(), 
+: idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable(),
   prevScope(), scope( 0 ), repScope( 0 ) { ++*stats().count; }
 
@@ -171,5 +171,5 @@
 }
 
-void SymbolTable::addDeletedId( const DeclWithType * decl, const Node * deleter ) {
+void SymbolTable::addDeletedId( const DeclWithType * decl, const Decl * deleter ) {
 	// default handling of conflicts is to raise an error
 	addId( decl, OnConflict::error(), nullptr, deleter );
@@ -189,5 +189,5 @@
 			}
 		}
-		// does not need to be added to the table if both existing and added have a base that are 
+		// does not need to be added to the table if both existing and added have a base that are
 		// the same
 		return true;
@@ -209,14 +209,14 @@
 	const std::string &id = decl->name;
 
-	if ( ! typeTable ) { 
+	if ( ! typeTable ) {
 		typeTable = TypeTable::new_ptr();
 	} else {
 		++*stats().map_lookups;
 		auto existing = typeTable->find( id );
-		if ( existing != typeTable->end() 
-			&& existing->second.scope == scope 
+		if ( existing != typeTable->end()
+			&& existing->second.scope == scope
 			&& addedTypeConflicts( existing->second.decl, decl ) ) return;
 	}
-	
+
 	lazyInitScope();
 	++*stats().map_mutations;
@@ -237,6 +237,6 @@
 		++*stats().map_lookups;
 		auto existing = structTable->find( id );
-		if ( existing != structTable->end()  
-			&& existing->second.scope == scope 
+		if ( existing != structTable->end()
+			&& existing->second.scope == scope
 			&& addedDeclConflicts( existing->second.decl, decl ) ) return;
 	}
@@ -256,9 +256,9 @@
 		++*stats().map_lookups;
 		auto existing = enumTable->find( id );
-		if ( existing != enumTable->end()  
-			&& existing->second.scope == scope 
+		if ( existing != enumTable->end()
+			&& existing->second.scope == scope
 			&& addedDeclConflicts( existing->second.decl, decl ) ) return;
 	}
-	
+
 	lazyInitScope();
 	++*stats().map_mutations;
@@ -279,6 +279,6 @@
 		++*stats().map_lookups;
 		auto existing = unionTable->find( id );
-		if ( existing != unionTable->end() 
-			&& existing->second.scope == scope 
+		if ( existing != unionTable->end()
+			&& existing->second.scope == scope
 			&& addedDeclConflicts( existing->second.decl, decl ) ) return;
 	}
@@ -298,6 +298,6 @@
 		++*stats().map_lookups;
 		auto existing = traitTable->find( id );
-		if ( existing != traitTable->end() 
-			&& existing->second.scope == scope 
+		if ( existing != traitTable->end()
+			&& existing->second.scope == scope
 			&& addedDeclConflicts( existing->second.decl, decl ) ) return;
 	}
@@ -309,15 +309,15 @@
 
 
-void SymbolTable::addWith( const std::vector< ptr<Expr> > & withExprs, const Node * withStmt ) {
+void SymbolTable::addWith( const std::vector< ptr<Expr> > & withExprs, const Decl * withStmt ) {
 	for ( const Expr * expr : withExprs ) {
 		if ( ! expr->result ) continue;
 		const Type * resTy = expr->result->stripReferences();
 		auto aggrType = dynamic_cast< const ReferenceToType * >( resTy );
-		assertf( aggrType, "WithStmt expr has non-aggregate type: %s", 
+		assertf( aggrType, "WithStmt expr has non-aggregate type: %s",
 			toString( expr->result ).c_str() );
 		const AggregateDecl * aggr = aggrType->aggr();
-		assertf( aggr, "WithStmt has null aggregate from type: %s", 
+		assertf( aggr, "WithStmt has null aggregate from type: %s",
 			toString( expr->result ).c_str() );
-		
+
 		addMembers( aggr, expr, OnConflict::deleteWith( withStmt ) );
 	}
@@ -373,7 +373,7 @@
 	}
 
-	/// gets the declaration for the function acting on a type specified by otype key, 
+	/// gets the declaration for the function acting on a type specified by otype key,
 	/// nullptr if none such
-	const FunctionDecl * getFunctionForOtype( 
+	const FunctionDecl * getFunctionForOtype(
 			const DeclWithType * decl, const std::string & otypeKey ) {
 		auto func = dynamic_cast< const FunctionDecl * >( decl );
@@ -383,13 +383,13 @@
 }
 
-bool SymbolTable::removeSpecialOverrides( 
+bool SymbolTable::removeSpecialOverrides(
 		SymbolTable::IdData & data, SymbolTable::MangleTable::Ptr & mangleTable ) {
-	// if a type contains user defined ctor/dtor/assign, then special rules trigger, which 
-	// determine the set of ctor/dtor/assign that can be used  by the requester. In particular, 
-	// if the user defines a default ctor, then the generated default ctor is unavailable, 
-	// likewise for copy ctor and dtor. If the user defines any ctor/dtor, then no generated 
-	// field ctors are available. If the user defines any ctor then the generated default ctor 
-	// is unavailable (intrinsic default ctor must be overridden exactly). If the user defines 
-	// anything that looks like a copy constructor, then the generated copy constructor is 
+	// if a type contains user defined ctor/dtor/assign, then special rules trigger, which
+	// determine the set of ctor/dtor/assign that can be used  by the requester. In particular,
+	// if the user defines a default ctor, then the generated default ctor is unavailable,
+	// likewise for copy ctor and dtor. If the user defines any ctor/dtor, then no generated
+	// field ctors are available. If the user defines any ctor then the generated default ctor
+	// is unavailable (intrinsic default ctor must be overridden exactly). If the user defines
+	// anything that looks like a copy constructor, then the generated copy constructor is
 	// unavailable, and likewise for the assignment operator.
 
@@ -450,5 +450,5 @@
 		// if this is the first user-defined function, delete non-user-defined overloads
 		std::vector< MangleTable::value_type > deleted;
-		
+
 		for ( const auto& entry : *mangleTable ) {
 			// skip decls that aren't functions or are for the wrong type
@@ -489,5 +489,5 @@
 			if ( dataIsCopyFunc ) {
 				// remove current function if exists a user-defined copy function
-				// since the signatures for copy functions don't need to match exactly, using 
+				// since the signatures for copy functions don't need to match exactly, using
 				// a delete statement is the wrong approach
 				if ( InitTweak::isCopyFunction( decl ) ) return false;
@@ -499,5 +499,5 @@
 		}
 	}
-	
+
 	// nothing (more) to fix, return true
 	return true;
@@ -525,18 +525,18 @@
 
 bool SymbolTable::addedIdConflicts(
-		const SymbolTable::IdData & existing, const DeclWithType * added, 
-		SymbolTable::OnConflict handleConflicts, const Node * deleter ) {
-	// if we're giving the same name mangling to things of different types then there is something 
+		const SymbolTable::IdData & existing, const DeclWithType * added,
+		SymbolTable::OnConflict handleConflicts, const Decl * deleter ) {
+	// if we're giving the same name mangling to things of different types then there is something
 	// wrong
 	assert( (isObject( added ) && isObject( existing.id ) )
 		|| ( isFunction( added ) && isFunction( existing.id ) ) );
-	
+
 	if ( existing.id->linkage.is_overrideable ) {
 		// new definition shadows the autogenerated one, even at the same scope
 		return false;
-	} else if ( existing.id->linkage.is_mangled 
-			|| ResolvExpr::typesCompatible( 
+	} else if ( existing.id->linkage.is_mangled
+			|| ResolvExpr::typesCompatible(
 				added->get_type(), existing.id->get_type(), SymbolTable{} ) ) {
-		
+
 		// it is a conflict if one declaration is deleted and the other is not
 		if ( deleter && ! existing.deleter ) {
@@ -555,7 +555,7 @@
 		if ( isDefinition( added ) && isDefinition( existing.id ) ) {
 			if ( handleConflicts.mode == OnConflict::Error ) {
-				SemanticError( added, 
-					isFunction( added ) ? 
-						"duplicate function definition for " : 
+				SemanticError( added,
+					isFunction( added ) ?
+						"duplicate function definition for " :
 						"duplicate object definition for " );
 			}
@@ -572,7 +572,7 @@
 }
 
-void SymbolTable::addId( 
-		const DeclWithType * decl, SymbolTable::OnConflict handleConflicts, const Expr * baseExpr, 
-		const Node * deleter ) {
+void SymbolTable::addId(
+		const DeclWithType * decl, SymbolTable::OnConflict handleConflicts, const Expr * baseExpr,
+		const Decl * deleter ) {
 	++*stats().add_calls;
 	const std::string &name = decl->name;
@@ -581,5 +581,5 @@
 	std::string mangleName;
 	if ( decl->linkage.is_overrideable ) {
-		// mangle the name without including the appropriate suffix, so overridable routines 
+		// mangle the name without including the appropriate suffix, so overridable routines
 		// are placed into the same "bucket" as their user defined versions.
 		mangleName = Mangle::mangle( decl, Mangle::Mode{ Mangle::NoOverrideable } );
@@ -588,5 +588,5 @@
 	}
 
-	// this ensures that no two declarations with the same unmangled name at the same scope 
+	// this ensures that no two declarations with the same unmangled name at the same scope
 	// both have C linkage
 	if ( decl->linkage.is_mangled ) {
@@ -596,5 +596,5 @@
 		}
 	} else {
-		// NOTE: only correct if name mangling is completely isomorphic to C 
+		// NOTE: only correct if name mangling is completely isomorphic to C
 		// type-compatibility, which it may not be.
 		if ( hasIncompatibleCDecl( name, mangleName ) ) {
@@ -628,6 +628,6 @@
 						idTable = idTable->set(
 							name,
-							mangleTable->set( 
-								mangleName, 
+							mangleTable->set(
+								mangleName,
 								IdData{ existing->second, handleConflicts.deleter } ) );
 					}
@@ -647,5 +647,5 @@
 }
 
-void SymbolTable::addMembers( 
+void SymbolTable::addMembers(
 		const AggregateDecl * aggr, const Expr * expr, SymbolTable::OnConflict handleConflicts ) {
 	for ( const Decl * decl : aggr->members ) {
@@ -655,9 +655,9 @@
 				const Type * t = dwt->get_type()->stripReferences();
 				if ( auto rty = dynamic_cast<const ReferenceToType *>( t ) ) {
-					if ( ! dynamic_cast<const StructInstType *>(rty) 
+					if ( ! dynamic_cast<const StructInstType *>(rty)
 						&& ! dynamic_cast<const UnionInstType *>(rty) ) continue;
 					ResolvExpr::Cost cost = ResolvExpr::Cost::zero;
 					const Expr * base = ResolvExpr::referenceToRvalueConversion( expr, cost );
-					addMembers( 
+					addMembers(
 						rty->aggr(), new MemberExpr{ base->location, dwt, base }, handleConflicts );
 				}
@@ -680,5 +680,5 @@
 		if ( ! decl.second.id->linkage.is_mangled && decl.first == mangleName ) return true;
 	}
-	
+
 	return false;
 }
Index: src/AST/SymbolTable.hpp
===================================================================
--- src/AST/SymbolTable.hpp	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
+++ src/AST/SymbolTable.hpp	(revision e67991fd01d5341ea7ee45736431dbe64851911e)
@@ -37,13 +37,13 @@
 		readonly<DeclWithType> id = nullptr;  ///< Identifier of declaration
 		readonly<Expr> baseExpr = nullptr;    ///< Implied containing aggregate (from WithExpr)
-		readonly<Node> deleter = nullptr;     ///< Node deleting this declaration (if non-null)
+		readonly<Decl> deleter = nullptr;     ///< Node deleting this declaration (if non-null)
 		unsigned long scope = 0;              ///< Scope of identifier
 
 		IdData() = default;
-		IdData( const DeclWithType * i, const Expr * base, const Node * del, unsigned long s ) 
+		IdData( const DeclWithType * i, const Expr * base, const Decl * del, unsigned long s )
 		: id( i ), baseExpr( base ), deleter( del ), scope( s ) {}
-		
+
 		/// Modify an existing node with a new deleter
-		IdData( const IdData & o, const Node * del )
+		IdData( const IdData & o, const Decl * del )
 		: id( o.id ), baseExpr( o.baseExpr ), deleter( del ), scope( o.scope ) {}
 
@@ -58,5 +58,5 @@
 	struct scoped {
 		readonly<D> decl;     ///< wrapped declaration
-		unsigned long scope;  ///< scope of this declaration 
+		unsigned long scope;  ///< scope of this declaration
 
 		scoped(const D * d, unsigned long s) : decl(d), scope(s) {}
@@ -88,5 +88,5 @@
 	~SymbolTable();
 
-	// when using an indexer manually (e.g., within a mutator traversal), it is necessary to 
+	// when using an indexer manually (e.g., within a mutator traversal), it is necessary to
 	// tell the indexer explicitly when scopes begin and end
 	void enterScope();
@@ -118,5 +118,5 @@
 	void addId( const DeclWithType * decl, const Expr * baseExpr = nullptr );
 	/// Adds a deleted identifier declaration to the symbol table
-	void addDeletedId( const DeclWithType * decl, const Node * deleter );
+	void addDeletedId( const DeclWithType * decl, const Decl * deleter );
 
 	/// Adds a type to the symbol table
@@ -136,5 +136,5 @@
 
 	/// adds all of the IDs from WithStmt exprs
-	void addWith( const std::vector< ptr<Expr> > & withExprs, const Node * withStmt );
+	void addWith( const std::vector< ptr<Expr> > & withExprs, const Decl * withStmt );
 
 	/// convenience function for adding a list of Ids to the indexer
@@ -154,5 +154,5 @@
 	const SymbolTable * atScope( unsigned long i ) const;
 
-	/// Removes matching autogenerated constructors and destructors so that they will not be 
+	/// Removes matching autogenerated constructors and destructors so that they will not be
 	/// selected. If returns false, passed decl should not be added.
 	bool removeSpecialOverrides( IdData & decl, MangleTable::Ptr & mangleTable );
@@ -164,25 +164,25 @@
 			Delete  ///< Delete the earlier version with the delete statement
 		} mode;
-		const Node * deleter;  ///< Statement that deletes this expression
+		const Decl * deleter;  ///< Statement that deletes this expression
 
 	private:
 		OnConflict() : mode(Error), deleter(nullptr) {}
-		OnConflict( const Node * d ) : mode(Delete), deleter(d) {}
+		OnConflict( const Decl * d ) : mode(Delete), deleter(d) {}
 	public:
 		OnConflict( const OnConflict& ) = default;
 
 		static OnConflict error() { return {}; }
-		static OnConflict deleteWith( const Node * d ) { return { d }; }
+		static OnConflict deleteWith( const Decl * d ) { return { d }; }
 	};
 
 	/// true if the existing identifier conflicts with the added identifier
 	bool addedIdConflicts(
-		const IdData & existing, const DeclWithType * added, OnConflict handleConflicts, 
-		const Node * deleter );
+		const IdData & existing, const DeclWithType * added, OnConflict handleConflicts,
+		const Decl * deleter );
 
 	/// common code for addId, addDeletedId, etc.
-	void addId( 
-		const DeclWithType * decl, OnConflict handleConflicts, const Expr * baseExpr = nullptr, 
-		const Node * deleter = nullptr );
+	void addId(
+		const DeclWithType * decl, OnConflict handleConflicts, const Expr * baseExpr = nullptr,
+		const Decl * deleter = nullptr );
 
 	/// adds all of the members of the Aggregate (addWith helper)
Index: src/AST/Visitor.hpp
===================================================================
--- src/AST/Visitor.hpp	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
+++ src/AST/Visitor.hpp	(revision e67991fd01d5341ea7ee45736431dbe64851911e)
@@ -48,5 +48,5 @@
     virtual const ast::Stmt *             visit( const ast::FinallyStmt          * ) = 0;
     virtual const ast::Stmt *             visit( const ast::WaitForStmt          * ) = 0;
-    virtual const ast::Stmt *             visit( const ast::WithStmt             * ) = 0;
+    virtual const ast::Decl *             visit( const ast::WithStmt             * ) = 0;
     virtual const ast::NullStmt *         visit( const ast::NullStmt             * ) = 0;
     virtual const ast::Stmt *             visit( const ast::DeclStmt             * ) = 0;
