Index: src/AST/Decl.hpp
===================================================================
--- src/AST/Decl.hpp	(revision 3648d98da574a68632d9d6b4d45ac64e674d5106)
+++ src/AST/Decl.hpp	(revision 89c2f7c92369856ac89bc39ac4e4671b2ac71fb3)
@@ -57,7 +57,7 @@
 	static readonly<Decl> fromId( UniqueId id );
 
-	virtual const Decl * accept( Visitor & v ) const override = 0;
-private:
-	virtual Decl * clone() const override = 0;
+	const Decl * accept( Visitor & v ) const override = 0;
+private:
+	Decl * clone() const override = 0;
 };
 
@@ -87,9 +87,9 @@
 	virtual const Type * get_type() const = 0;
 	/// Set type of this declaration. May be verified by subclass
-	virtual void set_type(Type*) = 0;
-
-	virtual const DeclWithType * accept( Visitor & v ) const override = 0;
-private:
-	virtual DeclWithType * clone() const override = 0;
+	virtual void set_type(Type *) = 0;
+
+	const DeclWithType * accept( Visitor & v ) const override = 0;
+private:
+	DeclWithType * clone() const override = 0;
 };
 
@@ -108,9 +108,35 @@
 
 	const Type* get_type() const override { return type; }
-	void set_type( Type* ty ) override { type = ty; }
-
-	virtual const DeclWithType * accept( Visitor& v ) const override { return v.visit( this ); }
-private:
-	virtual ObjectDecl * clone() const override { return new ObjectDecl{ *this }; }
+	void set_type( Type * ty ) override { type = ty; }
+
+	const DeclWithType * accept( Visitor& v ) const override { return v.visit( this ); }
+private:
+	ObjectDecl * clone() const override { return new ObjectDecl{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
+};
+
+class FunctionDecl : public DeclWithType {
+public:
+	ptr<FunctionType> type;
+	ptr<CompoundStmt> stmts;
+	std::list< ptr<Expr> > withExprs;
+
+	FunctionDecl( const CodeLocation & loc, const std::string &name, FunctionType * type,
+		CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::C,
+		std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {})
+	: DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), type( type ),
+	  stmts( stmts ) {}
+
+	const Type * get_type() const override { return type.get(); }
+	void set_type(Type * t) override { type = strict_dynamic_cast< FunctionType* >( t ); }
+
+	bool has_body() const { return stmts; }
+
+	const DeclWithType * accept( Visitor &v ) const override { return v.visit( this ); }
+private:
+	FunctionDecl * clone() const override { return new FunctionDecl( *this ); }
 
 	/// Must be copied in ALL derived classes
@@ -173,7 +199,11 @@
 	bool isComplete() { return sized; }
 
-	virtual const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
-	virtual TypeDecl * clone() const override { return new TypeDecl{ *this }; }
+	const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	TypeDecl * clone() const override { return new TypeDecl{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 };
 
@@ -187,7 +217,11 @@
 	std::string typeString() const override { return "typedef"; }
 
-	virtual const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
-	virtual TypedefDecl * clone() const override { return new TypedefDecl{ *this }; }
+	const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	TypedefDecl * clone() const override { return new TypedefDecl{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 };
 
@@ -227,7 +261,11 @@
 	bool is_thread() { return kind == DeclarationNode::Thread; }
 
-	virtual const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
-	virtual StructDecl * clone() const override { return new StructDecl{ *this }; }
+	const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	StructDecl * clone() const override { return new StructDecl{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 
 	std::string typeString() const override { return "struct"; }
@@ -241,7 +279,11 @@
 	: AggregateDecl( loc, name, std::move(attrs), linkage ) {}
 
-	virtual const Decl * accept( Visitor& v ) const override { return v.visit( this ); }
-private:
-	virtual UnionDecl * clone() const override { return new UnionDecl{ *this }; }
+	const Decl * accept( Visitor& v ) const override { return v.visit( this ); }
+private:
+	UnionDecl * clone() const override { return new UnionDecl{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 
 	std::string typeString() const override { return "union"; }
@@ -258,7 +300,11 @@
 	bool valueOf( Decl* enumerator, long long& value ) const;
 
-	virtual const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
-	virtual EnumDecl * clone() const override { return new EnumDecl{ *this }; }
+	const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	EnumDecl * clone() const override { return new EnumDecl{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 
 	std::string typeString() const override { return "enum"; }
@@ -275,11 +321,47 @@
 	: AggregateDecl( loc, name, std::move(attrs), linkage ) {}
 
-	virtual const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
-	virtual TraitDecl * clone() const override { return new TraitDecl{ *this }; }
+	const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	TraitDecl * clone() const override { return new TraitDecl{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 
 	std::string typeString() const override { return "trait"; }
 };
 
+class AsmDecl : public Decl {
+public:
+	ptr<AsmStmt> stmt;
+
+	AsmDecl( const CodeLocation & loc, AsmStmt *stmt )
+	: Decl( loc, "", {}, {} ), stmt(stmt) {}
+
+	const AsmDecl * accept( Visitor &v ) const override { return v.visit( this ); }
+private:
+	AsmDecl *clone() const override { return new AsmDecl( *this ); }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
+};
+
+class StaticAssertDecl : public Decl {
+public:
+	ptr<Expr> condition;
+	ptr<ConstantExpr> msg;   // string literal
+
+	StaticAssertDecl( const CodeLocation & loc, const Expr * condition, const ConstantExpr * msg )
+	: Decl( loc, "", {}, {} ), condition( condition ), msg( msg ) {}
+
+	const StaticAssertDecl * accept( Visitor &v ) const override { return v.visit( this ); }
+private:
+	StaticAssertDecl * clone() const override { return new StaticAssertDecl( *this ); }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
+};
 
 //=================================================================================================
@@ -294,6 +376,6 @@
 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 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); }
@@ -310,14 +392,10 @@
 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 FtypeDecl * node, Node::ref_type ref ) { node->increment(ref); }
-// inline void decrement( const class FtypeDecl * node, Node::ref_type ref ) { node->decrement(ref); }
-// inline void increment( const class DtypeDecl * node, Node::ref_type ref ) { node->increment(ref); }
-// inline void decrement( const class DtypeDecl * 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); }
+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); }
 
 }
Index: src/AST/Expr.hpp
===================================================================
--- src/AST/Expr.hpp	(revision 3648d98da574a68632d9d6b4d45ac64e674d5106)
+++ src/AST/Expr.hpp	(revision 89c2f7c92369856ac89bc39ac4e4671b2ac71fb3)
@@ -123,5 +123,5 @@
 	virtual const Expr * accept( Visitor & v ) const override = 0;
 private:
-	virtual Expr * clone() const override = 0;
+	Expr * clone() const override = 0;
 };
 
Index: src/AST/Fwd.hpp
===================================================================
--- src/AST/Fwd.hpp	(revision 3648d98da574a68632d9d6b4d45ac64e674d5106)
+++ src/AST/Fwd.hpp	(revision 89c2f7c92369856ac89bc39ac4e4671b2ac71fb3)
@@ -33,6 +33,4 @@
 class NamedTypeDecl;
 class TypeDecl;
-class FtypeDecl;
-class DtypeDecl;
 class TypedefDecl;
 class AsmDecl;
@@ -170,8 +168,4 @@
 inline void increment( const class TypeDecl *, Node::ref_type );
 inline void decrement( const class TypeDecl *, Node::ref_type );
-inline void increment( const class FtypeDecl *, Node::ref_type );
-inline void decrement( const class FtypeDecl *, Node::ref_type );
-inline void increment( const class DtypeDecl *, Node::ref_type );
-inline void decrement( const class DtypeDecl *, Node::ref_type );
 inline void increment( const class TypedefDecl *, Node::ref_type );
 inline void decrement( const class TypedefDecl *, Node::ref_type );
Index: src/AST/Init.hpp
===================================================================
--- src/AST/Init.hpp	(revision 3648d98da574a68632d9d6b4d45ac64e674d5106)
+++ src/AST/Init.hpp	(revision 89c2f7c92369856ac89bc39ac4e4671b2ac71fb3)
@@ -37,7 +37,7 @@
 	: ParseNode( loc ), designators( std::move(ds) ) {}
 
-	virtual const Designation* accept( Visitor& v ) const override { return v.visit( this ); }
+	const Designation* accept( Visitor& v ) const override { return v.visit( this ); }
 private:
-	virtual Designation* clone() const override { return new Designation{ *this }; }
+	Designation* clone() const override { return new Designation{ *this }; }
 };
 
@@ -52,7 +52,7 @@
 	Init( const CodeLocation& loc, ConstructFlag mc ) : ParseNode( loc ), maybeConstructed( mc ) {}
 
-	virtual const Init * accept( Visitor& v ) const override = 0;
+	const Init * accept( Visitor& v ) const override = 0;
 private:
-	virtual const Init * clone() const override = 0;
+	const Init * clone() const override = 0;
 };
 
@@ -66,7 +66,7 @@
 	: Init( loc, mc ), value( val ) {}
 
-	virtual const Init * accept( Visitor & v ) const override { return v.visit( this ); }
+	const Init * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
-	virtual SingleInit * clone() const override { return new SingleInit{ *this }; }
+	SingleInit * clone() const override { return new SingleInit{ *this }; }
 
 	/// Must be copied in ALL derived classes
@@ -94,7 +94,7 @@
 	const_iterator end() const { return initializers.end(); }
 
-	virtual const Init * accept( Visitor & v ) const override { return v.visit( this ); }
+	const Init * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
-	virtual ListInit * clone() const override { return new ListInit{ *this }; }
+	ListInit * clone() const override { return new ListInit{ *this }; }
 
 	/// Must be copied in ALL derived classes
@@ -117,7 +117,7 @@
 	: Init( loc, DoConstruct ), ctor( ctor ), dtor( dtor ), init( init ) {}
 
-	virtual const Init * accept( Visitor & v ) const override { return v.visit( this ); }
+	const Init * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
-	virtual ConstructorInit * clone() const override { return new ConstructorInit{ *this }; }
+	ConstructorInit * clone() const override { return new ConstructorInit{ *this }; }
 
 	/// Must be copied in ALL derived classes
Index: src/AST/Node.hpp
===================================================================
--- src/AST/Node.hpp	(revision 3648d98da574a68632d9d6b4d45ac64e674d5106)
+++ src/AST/Node.hpp	(revision 89c2f7c92369856ac89bc39ac4e4671b2ac71fb3)
@@ -9,7 +9,7 @@
 // Author           : Thierry Delisle
 // Created On       : Wed May 8 10:27:04 2019
-// Last Modified By : Aaron B. Moss
-// Last Modified On : Wed May 8 11:00:00 2019
-// Update Count     : 2
+// Last Modified By : Andrew Beach
+// Last Modified On : Wed May 15 16:02:00 2019
+// Update Count     : 3
 //
 
Index: src/AST/Pass.hpp
===================================================================
--- src/AST/Pass.hpp	(revision 3648d98da574a68632d9d6b4d45ac64e674d5106)
+++ src/AST/Pass.hpp	(revision 89c2f7c92369856ac89bc39ac4e4671b2ac71fb3)
@@ -85,97 +85,97 @@
 
 	/// Visit function declarations
-	virtual const ast::DeclWithType *     visit( const ast::ObjectDecl           * ) override final;
-	virtual const ast::DeclWithType *     visit( const ast::FunctionDecl         * ) override final;
-	virtual const ast::Decl *             visit( const ast::StructDecl           * ) override final;
-	virtual const ast::Decl *             visit( const ast::UnionDecl            * ) override final;
-	virtual const ast::Decl *             visit( const ast::EnumDecl             * ) override final;
-	virtual const ast::Decl *             visit( const ast::TraitDecl            * ) override final;
-	virtual const ast::Decl *             visit( const ast::TypeDecl             * ) override final;
-	virtual const ast::Decl *             visit( const ast::TypedefDecl          * ) override final;
-	virtual const ast::AsmDecl *          visit( const ast::AsmDecl              * ) override final;
-	virtual const ast::StaticAssertDecl * visit( const ast::StaticAssertDecl     * ) override final;
-	virtual const ast::CompoundStmt *     visit( const ast::CompoundStmt         * ) override final;
-	virtual const ast::Stmt *             visit( const ast::ExprStmt             * ) override final;
-	virtual const ast::Stmt *             visit( const ast::AsmStmt              * ) override final;
-	virtual const ast::Stmt *             visit( const ast::DirectiveStmt        * ) override final;
-	virtual const ast::Stmt *             visit( const ast::IfStmt               * ) override final;
-	virtual const ast::Stmt *             visit( const ast::WhileStmt            * ) override final;
-	virtual const ast::Stmt *             visit( const ast::ForStmt              * ) override final;
-	virtual const ast::Stmt *             visit( const ast::SwitchStmt           * ) override final;
-	virtual const ast::Stmt *             visit( const ast::CaseStmt             * ) override final;
-	virtual const ast::Stmt *             visit( const ast::BranchStmt           * ) override final;
-	virtual const ast::Stmt *             visit( const ast::ReturnStmt           * ) override final;
-	virtual const ast::Stmt *             visit( const ast::ThrowStmt            * ) override final;
-	virtual const ast::Stmt *             visit( const ast::TryStmt              * ) override final;
-	virtual const ast::Stmt *             visit( const ast::CatchStmt            * ) override final;
-	virtual const ast::Stmt *             visit( const ast::FinallyStmt          * ) override final;
-	virtual const ast::Stmt *             visit( const ast::WaitForStmt          * ) override final;
-	virtual const ast::Stmt *             visit( const ast::WithStmt             * ) override final;
-	virtual const ast::NullStmt *         visit( const ast::NullStmt             * ) override final;
-	virtual const ast::Stmt *             visit( const ast::DeclStmt             * ) override final;
-	virtual const ast::Stmt *             visit( const ast::ImplicitCtorDtorStmt * ) override final;
-	virtual const ast::Expr *             visit( const ast::ApplicationExpr      * ) override final;
-	virtual const ast::Expr *             visit( const ast::UntypedExpr          * ) override final;
-	virtual const ast::Expr *             visit( const ast::NameExpr             * ) override final;
-	virtual const ast::Expr *             visit( const ast::AddressExpr          * ) override final;
-	virtual const ast::Expr *             visit( const ast::LabelAddressExpr     * ) override final;
-	virtual const ast::Expr *             visit( const ast::CastExpr             * ) override final;
-	virtual const ast::Expr *             visit( const ast::KeywordCastExpr      * ) override final;
-	virtual const ast::Expr *             visit( const ast::VirtualCastExpr      * ) override final;
-	virtual const ast::Expr *             visit( const ast::UntypedMemberExpr    * ) override final;
-	virtual const ast::Expr *             visit( const ast::MemberExpr           * ) override final;
-	virtual const ast::Expr *             visit( const ast::VariableExpr         * ) override final;
-	virtual const ast::Expr *             visit( const ast::ConstantExpr         * ) override final;
-	virtual const ast::Expr *             visit( const ast::SizeofExpr           * ) override final;
-	virtual const ast::Expr *             visit( const ast::AlignofExpr          * ) override final;
-	virtual const ast::Expr *             visit( const ast::UntypedOffsetofExpr  * ) override final;
-	virtual const ast::Expr *             visit( const ast::OffsetofExpr         * ) override final;
-	virtual const ast::Expr *             visit( const ast::OffsetPackExpr       * ) override final;
-	virtual const ast::Expr *             visit( const ast::AttrExpr             * ) override final;
-	virtual const ast::Expr *             visit( const ast::LogicalExpr          * ) override final;
-	virtual const ast::Expr *             visit( const ast::ConditionalExpr      * ) override final;
-	virtual const ast::Expr *             visit( const ast::CommaExpr            * ) override final;
-	virtual const ast::Expr *             visit( const ast::TypeExpr             * ) override final;
-	virtual const ast::Expr *             visit( const ast::AsmExpr              * ) override final;
-	virtual const ast::Expr *             visit( const ast::ImplicitCopyCtorExpr * ) override final;
-	virtual const ast::Expr *             visit( const ast::ConstructorExpr      * ) override final;
-	virtual const ast::Expr *             visit( const ast::CompoundLiteralExpr  * ) override final;
-	virtual const ast::Expr *             visit( const ast::RangeExpr            * ) override final;
-	virtual const ast::Expr *             visit( const ast::UntypedTupleExpr     * ) override final;
-	virtual const ast::Expr *             visit( const ast::TupleExpr            * ) override final;
-	virtual const ast::Expr *             visit( const ast::TupleIndexExpr       * ) override final;
-	virtual const ast::Expr *             visit( const ast::TupleAssignExpr      * ) override final;
-	virtual const ast::Expr *             visit( const ast::StmtExpr             * ) override final;
-	virtual const ast::Expr *             visit( const ast::UniqueExpr           * ) override final;
-	virtual const ast::Expr *             visit( const ast::UntypedInitExpr      * ) override final;
-	virtual const ast::Expr *             visit( const ast::InitExpr             * ) override final;
-	virtual const ast::Expr *             visit( const ast::DeletedExpr          * ) override final;
-	virtual const ast::Expr *             visit( const ast::DefaultArgExpr       * ) override final;
-	virtual const ast::Expr *             visit( const ast::GenericExpr          * ) override final;
-	virtual const ast::Type *             visit( const ast::VoidType             * ) override final;
-	virtual const ast::Type *             visit( const ast::BasicType            * ) override final;
-	virtual const ast::Type *             visit( const ast::PointerType          * ) override final;
-	virtual const ast::Type *             visit( const ast::ArrayType            * ) override final;
-	virtual const ast::Type *             visit( const ast::ReferenceType        * ) override final;
-	virtual const ast::Type *             visit( const ast::QualifiedType        * ) override final;
-	virtual const ast::Type *             visit( const ast::FunctionType         * ) override final;
-	virtual const ast::Type *             visit( const ast::StructInstType       * ) override final;
-	virtual const ast::Type *             visit( const ast::UnionInstType        * ) override final;
-	virtual const ast::Type *             visit( const ast::EnumInstType         * ) override final;
-	virtual const ast::Type *             visit( const ast::TraitInstType        * ) override final;
-	virtual const ast::Type *             visit( const ast::TypeInstType         * ) override final;
-	virtual const ast::Type *             visit( const ast::TupleType            * ) override final;
-	virtual const ast::Type *             visit( const ast::TypeofType           * ) override final;
-	virtual const ast::Type *             visit( const ast::VarArgsType          * ) override final;
-	virtual const ast::Type *             visit( const ast::ZeroType             * ) override final;
-	virtual const ast::Type *             visit( const ast::OneType              * ) override final;
-	virtual const ast::Type *             visit( const ast::GlobalScopeType      * ) override final;
-	virtual const ast::Designation *      visit( const ast::Designation          * ) override final;
-	virtual const ast::Init *             visit( const ast::SingleInit           * ) override final;
-	virtual const ast::Init *             visit( const ast::ListInit             * ) override final;
-	virtual const ast::Init *             visit( const ast::ConstructorInit      * ) override final;
-	virtual const ast::Constant *         visit( const ast::Constant             * ) override final;
-	virtual const ast::Attribute *        visit( const ast::Attribute            * ) override final;
-	virtual const ast::TypeSubstitution * visit( const ast::TypeSubstitution     * ) override final;
+	const ast::DeclWithType *     visit( const ast::ObjectDecl           * ) override final;
+	const ast::DeclWithType *     visit( const ast::FunctionDecl         * ) override final;
+	const ast::Decl *             visit( const ast::StructDecl           * ) override final;
+	const ast::Decl *             visit( const ast::UnionDecl            * ) override final;
+	const ast::Decl *             visit( const ast::EnumDecl             * ) override final;
+	const ast::Decl *             visit( const ast::TraitDecl            * ) override final;
+	const ast::Decl *             visit( const ast::TypeDecl             * ) override final;
+	const ast::Decl *             visit( const ast::TypedefDecl          * ) override final;
+	const ast::AsmDecl *          visit( const ast::AsmDecl              * ) override final;
+	const ast::StaticAssertDecl * visit( const ast::StaticAssertDecl     * ) override final;
+	const ast::CompoundStmt *     visit( const ast::CompoundStmt         * ) override final;
+	const ast::Stmt *             visit( const ast::ExprStmt             * ) override final;
+	const ast::Stmt *             visit( const ast::AsmStmt              * ) override final;
+	const ast::Stmt *             visit( const ast::DirectiveStmt        * ) override final;
+	const ast::Stmt *             visit( const ast::IfStmt               * ) override final;
+	const ast::Stmt *             visit( const ast::WhileStmt            * ) override final;
+	const ast::Stmt *             visit( const ast::ForStmt              * ) override final;
+	const ast::Stmt *             visit( const ast::SwitchStmt           * ) override final;
+	const ast::Stmt *             visit( const ast::CaseStmt             * ) override final;
+	const ast::Stmt *             visit( const ast::BranchStmt           * ) override final;
+	const ast::Stmt *             visit( const ast::ReturnStmt           * ) override final;
+	const ast::Stmt *             visit( const ast::ThrowStmt            * ) override final;
+	const ast::Stmt *             visit( const ast::TryStmt              * ) override final;
+	const ast::Stmt *             visit( const ast::CatchStmt            * ) override final;
+	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::NullStmt *         visit( const ast::NullStmt             * ) override final;
+	const ast::Stmt *             visit( const ast::DeclStmt             * ) override final;
+	const ast::Stmt *             visit( const ast::ImplicitCtorDtorStmt * ) override final;
+	const ast::Expr *             visit( const ast::ApplicationExpr      * ) override final;
+	const ast::Expr *             visit( const ast::UntypedExpr          * ) override final;
+	const ast::Expr *             visit( const ast::NameExpr             * ) override final;
+	const ast::Expr *             visit( const ast::AddressExpr          * ) override final;
+	const ast::Expr *             visit( const ast::LabelAddressExpr     * ) override final;
+	const ast::Expr *             visit( const ast::CastExpr             * ) override final;
+	const ast::Expr *             visit( const ast::KeywordCastExpr      * ) override final;
+	const ast::Expr *             visit( const ast::VirtualCastExpr      * ) override final;
+	const ast::Expr *             visit( const ast::UntypedMemberExpr    * ) override final;
+	const ast::Expr *             visit( const ast::MemberExpr           * ) override final;
+	const ast::Expr *             visit( const ast::VariableExpr         * ) override final;
+	const ast::Expr *             visit( const ast::ConstantExpr         * ) override final;
+	const ast::Expr *             visit( const ast::SizeofExpr           * ) override final;
+	const ast::Expr *             visit( const ast::AlignofExpr          * ) override final;
+	const ast::Expr *             visit( const ast::UntypedOffsetofExpr  * ) override final;
+	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;
+	const ast::Expr *             visit( const ast::CommaExpr            * ) override final;
+	const ast::Expr *             visit( const ast::TypeExpr             * ) override final;
+	const ast::Expr *             visit( const ast::AsmExpr              * ) override final;
+	const ast::Expr *             visit( const ast::ImplicitCopyCtorExpr * ) override final;
+	const ast::Expr *             visit( const ast::ConstructorExpr      * ) override final;
+	const ast::Expr *             visit( const ast::CompoundLiteralExpr  * ) override final;
+	const ast::Expr *             visit( const ast::RangeExpr            * ) override final;
+	const ast::Expr *             visit( const ast::UntypedTupleExpr     * ) override final;
+	const ast::Expr *             visit( const ast::TupleExpr            * ) override final;
+	const ast::Expr *             visit( const ast::TupleIndexExpr       * ) override final;
+	const ast::Expr *             visit( const ast::TupleAssignExpr      * ) override final;
+	const ast::Expr *             visit( const ast::StmtExpr             * ) override final;
+	const ast::Expr *             visit( const ast::UniqueExpr           * ) override final;
+	const ast::Expr *             visit( const ast::UntypedInitExpr      * ) override final;
+	const ast::Expr *             visit( const ast::InitExpr             * ) override final;
+	const ast::Expr *             visit( const ast::DeletedExpr          * ) override final;
+	const ast::Expr *             visit( const ast::DefaultArgExpr       * ) override final;
+	const ast::Expr *             visit( const ast::GenericExpr          * ) override final;
+	const ast::Type *             visit( const ast::VoidType             * ) override final;
+	const ast::Type *             visit( const ast::BasicType            * ) override final;
+	const ast::Type *             visit( const ast::PointerType          * ) override final;
+	const ast::Type *             visit( const ast::ArrayType            * ) override final;
+	const ast::Type *             visit( const ast::ReferenceType        * ) override final;
+	const ast::Type *             visit( const ast::QualifiedType        * ) override final;
+	const ast::Type *             visit( const ast::FunctionType         * ) override final;
+	const ast::Type *             visit( const ast::StructInstType       * ) override final;
+	const ast::Type *             visit( const ast::UnionInstType        * ) override final;
+	const ast::Type *             visit( const ast::EnumInstType         * ) override final;
+	const ast::Type *             visit( const ast::TraitInstType        * ) override final;
+	const ast::Type *             visit( const ast::TypeInstType         * ) override final;
+	const ast::Type *             visit( const ast::TupleType            * ) override final;
+	const ast::Type *             visit( const ast::TypeofType           * ) override final;
+	const ast::Type *             visit( const ast::VarArgsType          * ) override final;
+	const ast::Type *             visit( const ast::ZeroType             * ) override final;
+	const ast::Type *             visit( const ast::OneType              * ) override final;
+	const ast::Type *             visit( const ast::GlobalScopeType      * ) override final;
+	const ast::Designation *      visit( const ast::Designation          * ) override final;
+	const ast::Init *             visit( const ast::SingleInit           * ) override final;
+	const ast::Init *             visit( const ast::ListInit             * ) override final;
+	const ast::Init *             visit( const ast::ConstructorInit      * ) override final;
+	const ast::Constant *         visit( const ast::Constant             * ) override final;
+	const ast::Attribute *        visit( const ast::Attribute            * ) override final;
+	const ast::TypeSubstitution * visit( const ast::TypeSubstitution     * ) override final;
 
 	friend void acceptAll( std::list< ptr<Decl> > & decls, Pass<pass_t>& visitor );
@@ -215,4 +215,7 @@
 		Pass<pass_t> & pass;
 	};
+
+private:
+	bool inFunction = false;
 };
 
Index: src/AST/Pass.impl.hpp
===================================================================
--- src/AST/Pass.impl.hpp	(revision 3648d98da574a68632d9d6b4d45ac64e674d5106)
+++ src/AST/Pass.impl.hpp	(revision 89c2f7c92369856ac89bc39ac4e4671b2ac71fb3)
@@ -158,8 +158,8 @@
 		// These may be modified by subnode but most be restored once we exit this statemnet.
 		ValueGuardPtr< const ast::TypeSubstitution * > __old_env         ( __pass::env( pass, 0) );
-		ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) > > __old_decls_before( stmts_before );
-		ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) > > __old_decls_after ( stmts_after  );
-		ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) > > __old_stmts_before( decls_before );
-		ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) > > __old_stmts_after ( decls_after  );
+		ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
+		ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
+		ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) >::type > __old_stmts_before( decls_before );
+		ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) >::type > __old_stmts_after ( decls_after  );
 
 		// Now is the time to actually visit the node
@@ -212,8 +212,8 @@
 
 		// These may be modified by subnode but most be restored once we exit this statemnet.
-		ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) > > __old_decls_before( stmts_before );
-		ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) > > __old_decls_after ( stmts_after  );
-		ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) > > __old_stmts_before( decls_before );
-		ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) > > __old_stmts_after ( decls_after  );
+		ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
+		ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
+		ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) >::type > __old_stmts_before( decls_before );
+		ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) >::type > __old_stmts_after ( decls_after  );
 
 		// update pass statitistics
@@ -390,9 +390,9 @@
 		{
 			guard_indexer guard { *this };
-			maybe_accept( node, &ast::ObjectDecl::type );
-		}
-		maybe_accept( node, &ast::ObjectDecl::init          );
-		maybe_accept( node, &ast::ObjectDecl::bitfieldWidth );
-		maybe_accept( node, &ast::ObjectDecl::attributes    );
+			maybe_accept( node, &ObjectDecl::type );
+		}
+		maybe_accept( node, &ObjectDecl::init          );
+		maybe_accept( node, &ObjectDecl::bitfieldWidth );
+		maybe_accept( node, &ObjectDecl::attributes    );
 	)
 
@@ -401,4 +401,217 @@
 	VISIT_END( DeclWithType, node );
 }
+
+//--------------------------------------------------------------------------
+// FunctionDecl
+template< typename pass_t >
+const ast::DeclWithType * ast::Pass< pass_t >::visit( const ast::FunctionDecl * node ) {
+	VISIT_START( node );
+
+	__pass::indexer::addId( pass, 0, node );
+
+	VISIT(maybe_accept( node, &FunctionDecl::withExprs );)
+	{
+		// with clause introduces a level of scope (for the with expression members).
+		// with clause exprs are added to the indexer before parameters so that parameters
+		// shadow with exprs and not the other way around.
+		guard_indexer guard { *this };
+		__pass::indexer::addWith( pass, 0, node->withExprs, node );
+		{
+			guard_indexer guard { *this };
+			// implicit add __func__ identifier as specified in the C manual 6.4.2.2
+			static ast::ObjectDecl func(
+				node->location, "__func__",
+				new ast::ArrayType(
+					new ast::BasicType( ast::BasicType::Char, ast::CV::Qualifiers( ast::CV::Const ) ),
+					nullptr, true, false
+				)
+			);
+			__pass::indexer::addId( pass, 0, &func );
+			VISIT(
+				maybe_accept( node, &FunctionDecl::type );
+				// function body needs to have the same scope as parameters - CompoundStmt will not enter
+				// a new scope if inFunction is true
+				ValueGuard< bool > oldInFunction( inFunction );
+				inFunction = true;
+				maybe_accept( node, &FunctionDecl::statements );
+				maybe_accept( node, &FunctionDecl::attributes );
+			)
+		}
+	}
+
+	VISIT_END( DeclWithType, node );
+}
+
+//--------------------------------------------------------------------------
+// StructDecl
+template< typename pass_t >
+const ast::Decl * ast::Pass< pass_t >::visit( const ast::StructDecl * node ) {
+	VISIT_START( node );
+
+	// make up a forward declaration and add it before processing the members
+	// needs to be on the heap because addStruct saves the pointer
+	__pass::indexer::addStructFwd( pass, 0, node );
+
+	VISIT({
+		guard_indexer guard { * this };
+		maybe_accept( node, &StructDecl::parameters );
+		maybe_accept( node, &StructDecl::members    );
+	})
+
+	// this addition replaces the forward declaration
+	__pass::indexer::addStruct( pass, 0, node );
+
+	VISIT_END( Decl, node );
+}
+
+//--------------------------------------------------------------------------
+// UnionDecl
+template< typename pass_t >
+const ast::Decl * ast::Pass< pass_t >::visit( const ast::UnionDecl * node ) {
+	VISIT_START( node );
+
+	// make up a forward declaration and add it before processing the members
+	__pass::indexer::addUnionFwd( pass, 0, node );
+
+	VISIT({
+		guard_indexer guard { * this };
+		maybe_accept( node, &UnionDecl::parameters );
+		maybe_accept( node, &UnionDecl::members    );
+	})
+
+	__pass::indexer::addUnion( pass, 0, node );
+
+	VISIT_END( Decl, node );
+}
+
+//--------------------------------------------------------------------------
+// EnumDecl
+template< typename pass_t >
+const ast::Decl * ast::Pass< pass_t >::visit( const ast::EnumDecl * node ) {
+	VISIT_START( node );
+
+	__pass::indexer::addEnum( pass, 0, node );
+
+	VISIT(
+		// unlike structs, traits, and unions, enums inject their members into the global scope
+		maybe_accept( node, &EnumDecl::parameters );
+		maybe_accept( node, &EnumDecl::members    );
+	)
+
+	VISIT_END( Decl, node );
+}
+
+//--------------------------------------------------------------------------
+// TraitDecl
+template< typename pass_t >
+const ast::Decl * ast::Pass< pass_t >::visit( const ast::TraitDecl * node ) {
+	VISIT_START( node );
+
+	VISIT({
+		guard_indexer guard { *this };
+		maybe_accept( node, &TraitDecl::parameters );
+		maybe_accept( node, &TraitDecl::members    );
+	})
+
+	__pass::indexer::addTrait( pass, 0, node );
+
+	VISIT_END( Decl, node );
+}
+
+//--------------------------------------------------------------------------
+// TypeDecl
+template< typename pass_t >
+const ast::Decl * ast::Pass< pass_t >::visit( const ast::TypeDecl * node ) {
+	VISIT_START( node );
+
+	VISIT({
+		guard_indexer guard { *this };
+		maybe_accept( node, &TypeDecl::parameters );
+		maybe_accept( node, &TypeDecl::base       );
+	})
+
+	// see A NOTE ON THE ORDER OF TRAVERSAL, above
+	// note that assertions come after the type is added to the symtab, since they are not part of the type proper
+	// and may depend on the type itself
+	__pass::indexer::addType( pass, 0, node );
+
+	VISIT(
+		maybe_accept( node, &TypeDecl::assertions, *this );
+
+		{
+			guard_indexer guard { *this };
+			maybe_accept( node, &TypeDecl::init );
+		}
+	)
+
+	VISIT_END( Decl, node );
+}
+
+//--------------------------------------------------------------------------
+// TypedefDecl
+template< typename pass_t >
+const ast::Decl * ast::Pass< pass_t >::visit( const ast::TypedefDecl * node ) {
+	VISIT_START( node );
+
+	VISIT({
+		guard_indexer guard { *this };
+		maybe_accept( node, &TypedefDecl::parameters );
+		maybe_accept( node, &TypedefDecl::base       );
+	})
+
+	__pass::indexer::addType( pass, 0, node );
+
+	maybe_accept( node, &TypedefDecl::assertions );
+
+	VISIT_END( Decl, node );
+}
+
+//--------------------------------------------------------------------------
+// AsmDecl
+template< typename pass_t >
+const ast::AsmDecl * ast::Pass< pass_t >::visit( const ast::AsmDecl * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		maybe_accept( node, &AsmDecl::stmt );
+	)
+
+	VISIT_END( AsmDecl, node );
+}
+
+//--------------------------------------------------------------------------
+// StaticAssertDecl
+template< typename pass_t >
+const ast::StaticAssertDecl * ast::Pass< pass_t >::visit( const ast::StaticAssertDecl * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		maybe_accept( node, &StaticAssertDecl::condition );
+		maybe_accept( node, &StaticAssertDecl::msg       );
+	)
+
+	VISIT_END( StaticAssertDecl, node );
+}
+
+//--------------------------------------------------------------------------
+// CompoundStmt
+template< typename pass_t >
+const ast::CompoundStmt * ast::Pass< pass_t >::visit( const ast::CompoundStmt * node ) {
+	VISIT_START( node );
+	VISIT({
+		// do not enter a new scope if inFunction is true - needs to check old state before the assignment
+		auto guard1 = makeFuncGuard( [this, inFunction = this->inFunction]() {
+			if ( ! inFunction ) __pass::indexer::enter(pass, 0);
+		}, [this, inFunction = this->inFunction]() {
+			if ( ! inFunction ) __pass::indexer::leave(pass, 0);
+		});
+		ValueGuard< bool > guard2( inFunction );
+		guard_scope guard3 { *this };
+		inFunction = false;
+		maybe_accept( node, &CompoundStmt::kids );
+	})
+	VISIT_END( CompoundStmt, node );
+}
+
 
 //--------------------------------------------------------------------------
Index: src/AST/Stmt.cpp
===================================================================
--- src/AST/Stmt.cpp	(revision 3648d98da574a68632d9d6b4d45ac64e674d5106)
+++ src/AST/Stmt.cpp	(revision 89c2f7c92369856ac89bc39ac4e4671b2ac71fb3)
@@ -8,8 +8,8 @@
 //
 // Author           : Aaron B. Moss
-// Created On       : Wed May 8 13:00:00 2019
-// Last Modified By : Aaron B. Moss
-// Last Modified On : Wed May 8 13:00:00 2019
-// Update Count     : 1
+// Created On       : Wed May  8 13:00:00 2019
+// Last Modified By : Andrew Beach
+// Last Modified On : Wed May 15 15:53:00 2019
+// Update Count     : 2
 //
 
@@ -18,10 +18,22 @@
 #include "DeclReplacer.hpp"
 
+namespace ast {
+
 // --- CompoundStmt
+CompoundStmt::CompoundStmt( const CompoundStmt& o ) : Stmt(o), kids(o.kids) {
+	assert(!"implemented");
+}
 
-namespace ast {
-	CompoundStmt::CompoundStmt( const CompoundStmt& o ) : Stmt(o), kids(o.kids) {
-		assert(!"implemented");
-	}
+// --- 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.
+	assert( Goto != kind || !target.empty() );
+}
+
+const char * BranchStmt::kindNames[] = {
+    "Goto", "Break", "Continue", "FallThrough", "FallThroughDefault"
+}
+
 }
 
Index: src/AST/Stmt.hpp
===================================================================
--- src/AST/Stmt.hpp	(revision 3648d98da574a68632d9d6b4d45ac64e674d5106)
+++ src/AST/Stmt.hpp	(revision 89c2f7c92369856ac89bc39ac4e4671b2ac71fb3)
@@ -8,8 +8,8 @@
 //
 // Author           : Aaron B. Moss
-// Created On       : Wed May 8 13:00:00 2019
-// Last Modified By : Aaron B. Moss
-// Last Modified On : Wed May 8 13:00:00 2019
-// Update Count     : 1
+// Created On       : Wed May  8 13:00:00 2019
+// Last Modified By : Andrew Beach
+// Last Modified On : Wed May 15 16:01:00 2019
+// Update Count     : 2
 //
 
@@ -40,7 +40,7 @@
 	Stmt(const Stmt& o) : ParseNode(o), labels(o.labels) {}
 
-	virtual const Stmt* accept( Visitor& v ) const override = 0;
-private:
-	virtual Stmt* clone() const override = 0;
+	const Stmt* accept( Visitor& v ) const override = 0;
+private:
+	Stmt* clone() const override = 0;
 };
 
@@ -59,7 +59,7 @@
 	void push_front( Stmt* s ) { kids.emplace_front( s ); }
 
-	virtual const CompoundStmt* accept( Visitor& v ) const override { return v.visit( this ); }
-private:
-	virtual CompoundStmt* clone() const override { return new CompoundStmt{ *this }; }
+	const CompoundStmt* accept( Visitor& v ) const override { return v.visit( this ); }
+private:
+	CompoundStmt* clone() const override { return new CompoundStmt{ *this }; }
 };
 
@@ -70,7 +70,7 @@
 	: Stmt(loc, std::move(labels)) {}
 
-	virtual const NullStmt * accept( Visitor& v ) const override { return v.visit( this ); }
-private:
-	virtual NullStmt * clone() const override { return new NullStmt{ *this }; }
+	const NullStmt* accept( Visitor& v ) const override { return v.visit( this ); }
+private:
+	NullStmt* clone() const override { return new NullStmt{ *this }; }
 };
 
@@ -80,12 +80,302 @@
 	ptr<Expr> expr;
 
-	ExprStmt( const CodeLocation& loc, Expr* e ) : Stmt(loc), expr(e) {}
-
-	virtual const Stmt * accept( Visitor& v ) const override { return v.visit( this ); }
-private:
-	virtual ExprStmt * clone() const override { return new ExprStmt{ *this }; }
-};
-
-
+	ExprStmt( const CodeLocation& loc, const Expr* e ) : Stmt(loc), expr(e) {}
+
+	const Stmt * accept( Visitor& v ) const override { return v.visit( this ); }
+private:
+	ExprStmt * clone() const override { return new ExprStmt{ *this }; }
+};
+
+class AsmStmt final : public Stmt {
+public:
+	bool isVolatile;
+	ptr<Expr> instruction;
+	std::vector<ptr<Expr>> output, input;
+	std::vector<ptr<ConstantExpr>> clobber;
+	std::vector<Label> gotoLabels;
+
+	AsmStmt( const CodeLocation& loc, bool isVolatile, const Expr * instruction,
+		std::vector<ptr<Expr>>&& output, std::vector<ptr<Expr>>&& input,
+		std::vector<ptr<ConstantExpr>>&& clobber, std::vector<Label>&& gotoLabels,
+		std::vector<Label>&& labels = {})
+	: Stmt(loc, std::move(labels)), isVolatile(isVolatile), instruction(instruction),
+	  output(std::move(output)), input(std::move(input)), clobber(std::move(clobber)),
+	  gotoLabels(std::move(gotoLabels)) {}
+
+	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
+private:
+	AsmStmt* clone() const override { return new AsmStmt{ *this }; }
+};
+
+class DirectiveStmt final : public Stmt {
+public:
+	std::string directive;
+
+	DirectiveStmt( const CodeLocation& loc, const std::string & directive,
+		std::vector<Label>&& labels = {} )
+	: Stmt(loc, std::move(labels)), directive(directive) {}
+
+	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
+private:
+	DirectiveStmt* clone() const override { return new DirectiveStmt{ *this }; }
+};
+
+class IfStmt final : public Stmt {
+public:
+	ptr<Expr> cond;
+	ptr<Stmt> thenPart;
+	ptr<Stmt> elsePart;
+	std::vector<ptr<Stmt>> inits;
+
+	IfStmt( const CodeLocation& loc, const Expr* cond, const Stmt* thenPart,
+		Stmt * const elsePart, std::vector<ptr<Stmt>>&& inits,
+		std::vector<Label>&& labels = {} )
+	: Stmt(loc, std::move(labels)), cond(cond), thenPart(thenPart), elsePart(elsePart),
+	  inits(std::move(inits)) {}
+
+	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
+private:
+	IfStmt* clone() const override { return new IfStmt{ *this }; }
+};
+
+class SwitchStmt final : public Stmt {
+public:
+	ptr<Expr> cond;
+	std::vector<ptr<Stmt>> stmts;
+
+	SwitchStmt( const CodeLocation& loc, const Expr* cond, std::vector<ptr<Stmt>>&& stmts,
+		std::vector<Label>&& labels = {} )
+	: Stmt(loc, std::move(labels)), cond(cond), stmts(std::move(stmts)) {}
+
+	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
+private:
+	SwitchStmt* clone() const override { return new SwitchStmt{ *this }; }
+};
+
+class CaseStmt final : public Stmt {
+public:
+	ptr<Expr> cond;
+	std::vector<ptr<Stmt>> stmts;
+
+    CaseStmt( const CodeLocation& loc, const Expr* cond, std::vector<ptr<Stmt>>&& stmts,
+        std::vector<Label>&& labels = {} )
+    : Stmt(loc, std::move(labels)), cond(cond), stmts(std::move(stmts)) {}
+
+	bool isDefault() { return !cond; }
+
+	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
+private:
+	CaseStmt* clone() const override { return new CaseStmt{ *this }; }
+};
+
+class WhileStmt final : public Stmt {
+public:
+	ptr<Expr> cond;
+	ptr<Stmt> body;
+	std::vector<ptr<Stmt>> inits;
+	bool isDoWhile;
+
+	WhileStmt( const CodeLocation& loc, const Expr* cond, const Stmt* body,
+		std::vector<ptr<Stmt>>&& inits, bool isDoWhile = false, std::vector<Label>&& labels = {} )
+	: Stmt(loc, std::move(labels)), cond(cond), body(body), inits(std::move(inits)),
+	  isDoWhile(isDoWhile) {}
+
+	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
+private:
+	WhileStmt* clone() const override { return new WhileStmt{ *this }; }
+};
+
+class ForStmt final : public Stmt {
+public:
+	std::vector<ptr<Stmt>> inits;
+	ptr<Expr> cond;
+	ptr<Expr> increment;
+	ptr<Stmt> body;
+
+	ForStmt( const CodeLocation& loc, std::vector<ptr<Stmt>>&& inits, const Expr* cond,
+		const Expr* increment, const Stmt* body, std::vector<Label>&& labels = {} )
+	: Stmt(loc, std::move(labels)), inits(std::move(inits)), cond(cond), increment(increment),
+	  body(body) {}
+
+	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
+private:
+	ForStmt* clone() const override { return new ForStmt{ *this }; }
+};
+
+class BranchStmt final : public Stmt {
+public:
+	enum Kind { Goto, Break, Continue, FallThrough, FallThroughDefault };
+	static constexpr size_t kindEnd = 1 + (size_t)FallThroughDefault;
+
+	const Label originalTarget;
+	Label target;
+	ptr<Expr> computedTarget;
+	Kind kind;
+
+	BranchStmt( const CodeLocation& loc, Kind kind, Label target,
+		std::vector<Label>&& labels = {} );
+	BranchStmt( const CodeLocation& loc, const Expr* computedTarget,
+		std::vector<Label>&& labels = {} )
+	: Stmt(loc, std::move(labels)), originalTarget(loc), target(loc),
+	  computedTarget(computedTarget), kind(Goto) {}
+
+	const char * kindName() { return kindNames[kind]; }
+
+	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
+private:
+	BranchStmt* clone() const override { return new BranchStmt{ *this }; }
+	static const char * kindNames[kindEnd];
+};
+
+class ReturnStmt final : public Stmt {
+public:
+	ptr<Expr> expr;
+
+	ReturnStmt( const CodeLocation& loc, const Expr* expr, std::vector<Label>&& labels = {} )
+	: Stmt(loc, std::move(labels)), expr(expr) {}
+
+	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
+private:
+	ReturnStmt* clone() const override { return new ReturnStmt{ *this }; }
+};
+
+class ThrowStmt final : public Stmt {
+public:
+	enum Kind { Terminate, Resume };
+
+	ptr<Expr> expr;
+	ptr<Expr> target;
+	Kind kind;
+
+	ThrowStmt( const CodeLocation& loc, Kind kind, const Expr* expr, const Expr* target,
+		std::vector<Label>&& labels = {} )
+	: Stmt(loc, std::move(labels)), expr(expr), target(target), kind(kind) {}
+
+	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
+private:
+	ThrowStmt* clone() const override { return new ThrowStmt{ *this }; }
+};
+
+class TryStmt final : public Stmt {
+public:
+	ptr<CompoundStmt> body;
+	std::vector<ptr<CatchStmt>> handlers;
+	ptr<FinallyStmt> finally;
+
+	TryStmt( const CodeLocation& loc, const CompoundStmt* body,
+		std::vector<ptr<CatchStmt>>&& handlers, const FinallyStmt* finally,
+		std::vector<Label>&& labels = {} )
+	: Stmt(loc, std::move(labels)), body(body), handlers(std::move(handlers)), finally(finally) {}
+
+	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
+private:
+	TryStmt* clone() const override { return new TryStmt{ *this }; }
+};
+
+class CatchStmt final : public Stmt {
+public:
+	enum Kind { Terminate, Resume };
+
+	ptr<Decl> decl;
+	ptr<Expr> cond;
+	ptr<Stmt> body;
+	Kind kind;
+
+	CatchStmt( const CodeLocation& loc, Kind kind, const Decl* decl, const Expr* cond,
+		const Stmt* body, std::vector<Label>&& labels = {} )
+	: Stmt(loc, std::move(labels)), decl(decl), cond(cond), body(body), kind(kind) {}
+
+	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
+private:
+	CatchStmt* clone() const override { return new CatchStmt{ *this }; }
+};
+
+class FinallyStmt final : public Stmt {
+public:
+	ptr<CompoundStmt> body;
+
+	FinallyStmt( const CodeLocation& loc, const CompoundStmt* body,
+		std::vector<Label>&& labels = {} )
+	: Stmt(loc, std::move(labels)), body(body) {}
+
+	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
+private:
+	FinallyStmt* clone() const override { return new FinallyStmt{ *this }; }
+};
+
+class WaitForStmt final : public Stmt {
+public:
+	struct Target {
+		ptr<Expr> function;
+		std::vector<ptr<Expr>> arguments;
+	};
+
+	struct Clause {
+		Target target;
+		ptr<Stmt> stmt;
+		ptr<Expr> cond;
+	};
+
+	struct Timeout {
+		ptr<Expr> time;
+		ptr<Stmt> stmt;
+		ptr<Expr> cond;
+	};
+
+	struct OrElse {
+		ptr<Stmt> stmt;
+		ptr<Expr> cond;
+	};
+
+	std::vector<Clause> clauses;
+	Timeout timeout;
+	OrElse orElse;
+
+	WaitForStmt( const CodeLocation& loc, std::vector<Label>&& labels = {} )
+	: Stmt(loc, std::move(labels)) {}
+
+	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
+private:
+	WaitForStmt* clone() const override { return new WaitForStmt{ *this }; }
+};
+
+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 }; }
+};
+
+class DeclStmt final : public Stmt {
+public:
+	ptr<Decl> decl;
+
+	DeclStmt( const CodeLocation& loc, const Decl* decl, std::vector<Label>&& labels = {} )
+	: Stmt(loc, std::move(labels)), decl(decl) {}
+
+	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
+private:
+	DeclStmt* clone() const override { return new DeclStmt{ *this }; }
+};
+
+class ImplicitCtorDtorStmt final : public Stmt {
+public:
+	readonly<Stmt> callStmt;
+
+	ImplicitCtorDtorStmt( const CodeLocation& loc, const Stmt* callStmt,
+		std::vector<Label>&& labels = {} )
+	: Stmt(loc, std::move(labels)), callStmt(callStmt) {}
+
+	const Stmt* accept( Visitor& v ) const override { return v.visit( this ); }
+private:
+	ImplicitCtorDtorStmt* clone() const override { return new ImplicitCtorDtorStmt{ *this }; }
+};
 
 //=================================================================================================
Index: src/AST/porting.md
===================================================================
--- src/AST/porting.md	(revision 3648d98da574a68632d9d6b4d45ac64e674d5106)
+++ src/AST/porting.md	(revision 89c2f7c92369856ac89bc39ac4e4671b2ac71fb3)
@@ -122,4 +122,21 @@
 * `get_statement()` exclusively used for code location, replaced with `CodeLocation` field
 
+`CaseStmt`
+* `_isDefault` has been removed
+  * `isDefault` calculates value from `cond`
+  * default may not have a condition. I believe case (!default) requires a condition.
+
+`BranchStmt`
+* `Type` -> `Kind` and `type` -> `kind`
+* Constructors no longer throw SemanticErrorException:
+  * `label` constructor claims it is now considered a syntax error, replaced with assert.
+  * `computedTarget` constructor assumes `Goto`, other check would have SegFaulted.
+
+`TryStmt`
+* `block` -> `body` and `finallyBlock` -> `finally`
+
+`FinallyStmt`
+* `block` -> `body`
+
 `CompoundStmt`
 * **TODO** port copy operator
