Index: c/proposals/virtual.txt
===================================================================
--- doc/proposals/virtual.txt	(revision 9e1d48503286c2f21bf3f599590920efc8b02293)
+++ 	(revision )
@@ -1,370 +1,0 @@
-Proposal for virtual functionality
-
-There are two types of virtual inheritance in this proposal, relaxed
-(implicit) and strict (explicit). Relaxed is the simpler case that uses the
-existing trait system with the addition of trait references and vtables.
-Strict adds some constraints and requires some additional notation but allows
-for down-casting.
-
-Relaxed Virtual Inheritance:
-
-Imagine the following code :
-
-trait drawable(otype T) {
-      void draw(T* );
-};
-
-struct text {
-      char* text;
-};
-
-void draw(text*);
-
-struct line{
-      vec2 start;
-      vec2 end;
-};
-
-void draw(line*);
-
-While all the members of this simple UI support drawing, creating a UI that
-easily supports both these UI requires some tedious boiler-plate code:
-
-enum type_t { text, line };
-
-struct widget {
-      type_t type;
-      union {
-            text t;
-            line l;
-      };
-};
-
-void draw(widget* w) {
-      switch(w->type) {
-            case text : draw(&w->text); break;
-            case line : draw(&w->line); break;
-            default : handle_error(); break;
-      }
-}
-
-While this code will work as implemented, adding any new widgets or any new
-widget behaviors requires changing existing code to add the desired
-functionality. To ease this maintenance effort required CFA introduces the
-concept of trait references.
-
-Using trait references to implement the above gives the following :
-
-trait drawable objects[10];
-fill_objects(objects);
-
-while(running) {
-      for(drawable object : objects) {
-            draw(object);
-      }
-}
-
-The keyword trait is optional (by the same rules as the struct keyword). This
-is not currently supported in CFA and the lookup is not possible to implement
-statically. Therefore we need to add a new feature to handle having dynamic
-lookups like this.
-
-What we really want to do is express the fact that calling draw() on a trait
-reference should find the underlying type of the given parameter and find how
-it implements the routine, as in the example with the enumeration and union.
-
-For instance specifying that the drawable trait reference looks up the type
-of the first argument to find the implementation would be :
-
-trait drawable(otype T) {
-      void draw(virtual T* );
-};
-
-This could be implied in simple cases like this one (single parameter on the
-trait and single generic parameter on the function). In more complex cases it
-would have to be explicitly given, or a strong convention would have to be
-enforced (e.g. implementation of trait functions is always drawn from the
-first polymorphic parameter).
-
-Instances of a trait are created by wrapping an existing instance of a type
-that implements that trait. This wrapper includes all the function pointers
-and other values required to preform the dynamic look-up. These are chosen by
-the normal look-up rules at the point of abstraction.
-
-One of the limitations of this design is that it does not support double
-dispatching, which concretely means traits cannot have routines with more than
-one virtual parameter. The program must have a single table to look up the
-function on. Using trait references with traits with more than one parameter
-is also restricted, initially forbidden, see extension.
-
-Ownership of the underlying structure is also a bit of a trick. Considering
-the use cases for trait object, it is probably best to have the underlying
-object be heap allocated and owned by the trait object.
-
-Extension: Multi-parameter Virtual Traits:
-
-This implementation can be extended to traits with multiple parameters if
-one is called out as being the virtual trait. For example :
-
-trait iterator(otype T, dtype Item) {
-	Maybe(Item) next(virtual T *);
-}
-
-iterator(int) generators[10];
-
-Which creates a collection of iterators that produce integers, regardless of
-how those iterators are implemented. This may require a note that this trait
-is virtual on T and not Item, but noting it on the functions may be enough.
-
-
-Strict Virtual Inheritance:
-
-One powerful feature relaxed virtual does not support is the idea of down
-casting. Once something has been converted into a trait reference there is
-very little we can do to recover and of the type information, only the trait's
-required function implementations are kept.
-
-To allow down casting strict virtual requires that all traits and structures
-involved be organized into a tree. Each trait or struct must have a unique
-position on this tree (no multiple inheritance).
-
-This is declared as follows :
-
-trait error(otype T) virtual {
-	const char * msg(T *);
-}
-
-trait io_error(otype T) virtual error {
-	FILE * src(T *);
-}
-
-struct eof_error virtual io_error {
-	FILE * fd;
-};
-
-So the trait error is the head of a new tree and io_error is a child of it.
-
-Also the parent trait is implicitly part of the assertions of the children,
-so all children implement the same operations as the parent. By the unique
-path down the tree, we can also uniquely order them so that a prefix of a
-child's vtable has the same format as its parent's.
-
-This gives us an important extra feature, runtime checking of the parent-child
-relationship with virtual cast, where a pointer (and maybe a reference) to
-a virtual type can be cast to another virtual cast. However the cast is
-dynamicly check and only occurs if the underlying type is a child of the type
-being cast to. Otherwise null is returned.
-
-(virtual TYPE)EXPR
-
-As an extention, the TYPE may be ommitted if it can be determained from
-context, for instance if the cast occurs on the right hand side of an
-assignment.
-
-Function look-up follows the same rules as relaxed (behavioural) inheritance.
-Traits can be upcast and down cast without losing information unless the
-trait is cast down to a structure. Here there are two options.
-
-  Abstraction Time Binding: The more efficient and consistant with other parts
-of CFA. Only the trait types use dynamic look-up, if converveted back into a
-structure the normal static look-up rules find the function at compile time.
-Casting down to a structure type can then result in the loss of a set of
-bindings.
-  Construction Time Binding: For more consistant handling of the virtual
-structs, they are always considered wrapped. Functions are bound to the
-instance the moment it is constructed and remain unchanged throughout its
-lifetime, so down casting does not lose information.
-
-(We will have to decide between one of these two.)
-
-Extension: Multiple Parents
-
-Although each trait/struct must have a unique position on each tree, it could
-have positions on multiple trees. All this requires is the ability to give
-multiple parents, as here :
-
-trait region(otype T) virtual drawable, collider;
-
-The restriction being, the parents must come from different trees. This
-object (and all of its children) can be cast to either tree. This is handled
-by generating a separate vtable for each tree the structure is in.
-
-Extension: Multi-parameter Strict Virtual
-
-If a trait has multiple parameters then one must be called out to be the one
-we generate separate vtables for, as in :
-
-trait example(otype T, otype U) virtual(T) ...
-
-This can generate a separate vtable for each U for which all the T+U
-implementations are provided. These are then separate nodes in the tree (or
-the root of different trees) as if each was created individually. Providing a
-single unique instance of these nodes would be the most difficult aspect of
-this extension, possibly intractable, though with sufficient hoisting and
-link-once duplication it may be possible.
-
-Example:
-
-trait argument(otype T) virtual {
-	char short_name(virtual T *);
-	bool is_set(virtual T *);
-};
-
-trait value_argument(otype T, otype U) virtual(T) argument {
-	U get_value(virtual T *);
-};
-
-Extension: Structural Inheritance
-
-Currently traits must be the internal nodes and structs the leaf nodes.
-Structs could be made internal nodes as well, in which case the child structs
-would likely structurally inherit the fields of their parents.
-
-
-Storing the Virtual Lookup Table (vtable):
-
-We have so far been silent on how the vtable is created, stored and accessed.
-The vtables for the two types might be handled slightly differently and then
-there is also the hierarchy data for virtual casts.
-
-The hierarchy data is simple conceptually. A single (exactly one copy) pointer
-for each type can act as the identity for it. The value of the pointer is
-its parent type, with the root pointer being NULL. Additional meta-data
-can accompany the parent pointer, such as a string name or the vtable fields.
-
-They types of each vtable can be constructed from the definitions of the
-traits (or internal nodes). The stand alone/base vtable is the same for both
-kinds of inheritance. It may be argumented differently however (include parent
-/this pointer in hierachal inheritance).
-
-Creation of the actual vtable is tricky. For classical single implementation
-semantics we would assemble the functions and create one vtable at compile
-time. However, not only does this not give CFA-like behaviour, it is
-impossible generally because types can satify assertions in different ways at
-different times and stop satifying them. A special set of harder rules could
-be used, instead we have decided to try creating multiple vtables for each
-type. The different vtables will all implement the same type but not always
-in the same way.
-
-Storage has some issues from creation. If the contents of every vtable could
-be determained at compile time they could all be created and stored
-statically. However since thunks can be constructed on the stack and become
-the best match, that isn't always possible. Those will have to be stored in
-dynamic memory. Which means that all vtables must be stored dynamically or
-there must be a way to determain which ones to free when the trait object is
-destroyed.
-
-Access has two main options:
-
-The first is through the use of fat pointers, or a tuple of pointers. When the
-object is converted to a trait reference, the pointers to its vtables are
-stored along side it.
-
-This allows for compatibility with existing structures (such as those imported
-from C) and is the default storage method unless a different one is given.
-
-The other is by inlining the vtable pointer as "intrusive vtables". This adds
-a field to the structure to the vtable. The trait reference then has a single
-pointer to this field, the vtable includes an offset to find the beginning of
-the structure again.
-
-This is used if you specify a vtable field in the structure. If given in the
-trait the vtable pointer in the trait reference can then become a single
-pointer to the vtable field and use that to recover the original object
-pointer as well as retrieve all operations.
-
-trait drawable(otype T) {
-	vtable drawable;
-};
-
-struct line {
-	vtable drawable;
-	vec2 start;
-	vec2 end;
-};
-
-This inline code allows trait references to be converted to plain pointers
-(although they still must be called specially). The vtable field may just be
-an opaque block of memory or it may allow user access to the vtable. If so
-then there should be some way to retrieve the type of the vtable, which will be
-autogenerated and often unique.
-
-It may be worth looking into a way to force the vtable pointer to be in a
-particular location, which would save the storage to store the offset and
-maybe the offset operation itself (offset = 0). However it may not be worth
-introducing a new language feature for.
-As of writing, exceptions actually use this system.
-
-
-Keyword Usage:
-
-It may be desirable to add fewer new keywords than discussed in this proposal.
-It is possible that "virtual" could replace both "vtable" above with
-unambiguous contextual meaning. However, for purposes of clarity in the design
-discussion it is beneficial to keep the keywords for separate concepts distinct.
-
-
-Trait References and Operations:
-
-sizeof(drawable) will return the size of the trait object itself. However :
-
-line a_line;
-drawable widget = a_line;
-sizeof(widget);
-
-Will instead return the sizeof the underlying object, although the trait must
-require that its implementation is sized for there to be a meaningful value
-to return. You may also get the size of the trait reference with
-
-sizeof(&widget);
-
-Calling free on a trait reference will free the memory for the object. It will
-leave the vtables alone, as those are (always?) statically allocated.
-
-
-Special Traits:
-
-trait is_virtual_parent(dtype parent, dtype child) { ... };
-
-There are others but I believe this one to be the most important. The trait
-holds if the parent type is a strict virtual ancestor (any number of levels)
-of child. It will have to exist at least internally to check for upcasts and
-it can also be used to optimize virtual casts into upcasts. Or a null value or
-error if the cast would never succeed. Exporting it to a special trait allows
-users to express that requirement in their own polymorphic code.
-
-
-Implementation:
-
-Before we can generate any of the nessasary code, the compiler has to get some
-additional information about the code that it currently does not collect.
-
-First it should establish all child->parent links so that it may travel up the
-hierarchy to grab the nessasary information, and create the actual parent
-pointers in the strict virtual tables. It should also maintain the connections
-between the virtual type (structure or trait), the vtable type and the vtable
-instance (or default instance for relaxed virtual if multiple are allowed). To
-this end a sub-node should be created with the nessasary pointers. Traits and
-structs with virtual can create an instance and store all the nessasary data.
-
-With the hierarchy in place it can generate the vtable type for each type,
-it will generally have a function pointer field for each type assertion in
-some consistant order. Strict virtual will also have a pointer to the parent's
-vtable and intrusive vtables will also have the offset to recover the original
-pointer. Sized types will also carry the size.
-
-Wheither the vtable is intrusive or not should also be save so that the trait
-object/reference/pointer knows if it has to store 1 or 2 pointers. A wrapper
-function will have to be generated for each type assertion so that they may
-be called on the trait type, these can probably be inlined.
-
-The virtual parameter will also have to be marked (implicately or explicately)
-until code generation so that the wrapper functions know where to go to get
-the vtable for the function look up. That could probably be added as a
-storageclass, although one that is only valid on type assertions.
-
-The generated vtable will than have to have a vtable instance created and
-filled with all the approprate values. Stricter matching may have to be used
-to ensure that the functions used are stable. It will also have to use
-".gnu.linkonce" or equilant to ensure only one copy exists in the final code
-base.
Index: doc/proposals/vtable.md
===================================================================
--- doc/proposals/vtable.md	(revision 9e1d48503286c2f21bf3f599590920efc8b02293)
+++ doc/proposals/vtable.md	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
@@ -1,9 +1,4 @@
 Proposal For Use of Virtual Tables
 ==================================
-
-This is an adaptation of the earlier virtual proposal, updating it with new
-ideas, re-framing it and laying out more design decisions. It should
-eventually replace the earlier proposal, but not all features and syntax have
-been converted to the new design.
 
 The basic concept of a virtual table (vtable) is the same here as in most
@@ -93,4 +88,8 @@
         }
     }
+
+With a more complete widget trait you could, for example, construct a UI tool
+kit that can declare containers that hold widgets without knowing about the
+widget types. Making it reasonable to extend the tool kit.
 
 The trait types can also be used in the types of assertions on traits as well.
@@ -244,13 +243,14 @@
 We would also like to implement hierarchical relations between types.
 
-    AstNode
-    |-ParseNode
-    | |-Declaration
-    | | |-DeclarationWithType
-    | | |-StructureDeclaration
-    | |-Statement
-    | | |-CompoundStatement
-    | |-Expression
-    |-Type
+    ast_node
+    |-expression_node
+    | |-operator_expression
+    |
+    |-statement_node
+    | |-goto_statement
+    |
+    |-declaration_node
+      |-using_declaration
+      |-variable_declaration
 
 Virtual tables by themselves are not quite enough to implement this system.
@@ -315,4 +315,10 @@
     }
 
+This system does not support multiple inheritance. The system could be
+extended to support it or a limited form (ex. you may have multiple parents
+but they may not have a common ancestor). However this proposal focuses just
+on using hierachy as organization. Other uses for reusable/genaric code or
+shared interfaces is left for other features of the language.
+
 ### Extension: Structural Inheritance
 An extension would be allow structures to be used as internal nodes on the
@@ -354,5 +360,5 @@
 solution but only works if we have exactly 1 vtable for each type. The second
 is to put a pointer to the type id in each vtable. This has more overhead but
-allows multiple vtables.
+allows multiple vtables per type.
 
     struct <trait>_vtable {
@@ -367,4 +373,7 @@
         // Trait dependent list of vtable members.
     };
+
+One important restriction is that only one instance of each typeid in memory.
+There is a ".gnu.linkonce" feature in the linker that might solve the issue.
 
 ### Virtual Casts
@@ -423,4 +432,37 @@
     io_error * error = (virtual)exc;
 
+#### Sample Implementation
+This cast implementation assumes a type id layout similar to the one given
+above. Also this code is definitely in the underlying C. Functions that give
+this functionality could exist in the standard library but these are meant to
+be produced by code translation of the virtual cast.
+
+    bool is_in_subtree(typeid const * root, typeid const * id) {
+        if (root == id) {
+            return true
+        } else if (NULL == id->parent) {
+            return false;
+        } else {
+            return is_in_subtree(root, id->parent);
+        }
+    }
+
+    void * virtual_cast(typeid const * target, void * value) {
+        return is_in_subtree(target, *(typeid const **)value) ? value : NULL;
+    }
+
+The virtual cast function might have to be wrapped with some casts to make it
+compile without warning.
+
+For the implicate target type we may be able to lean on the type resolution
+system that already exists. If the casting to ancestor type is built into
+the resolution then the impicate target could be decided by picking an
+overload, generated for each hierarchial type (here io_error and its root
+type exception).
+
+    io_error * virtual_cast(exception * value) {
+        return virtual_cast(io_error_typeid, value);
+    }
+
 ### Extension: Inline vtables
 Since the structures here are usually made to be turned into trait objects
@@ -436,4 +478,8 @@
 to allow access to all three options.
 
+The pointer to virtual table field on structures might implicately added (the
+types have to declare they are a child here) or created with a declaration,
+possibly like the one used to create the assertion.
+
 ### Virtual Tables as Types
 Here we consider encoding plus the implementation of functions on it to be a
@@ -442,4 +488,20 @@
 and implementation.
 
+### Question: Wrapping Structures
+One issue is what to do with concrete types at the base of the type tree.
+When we are working with the concrete type generally it would like them to be
+regular structures with direct calls. On the other hand for interactions with
+other types in the hierarchy it is more convenent for the type already to be
+cast.
+
+Which of these two should we use? Should we support both and if so how do we
+choose which one is being used at any given time.
+
+On a related note I have been using pointers two trait types here, as that
+is how many existing languages handle it. However the generic objects might
+be only one or two pointers wide passing the objects as a whole would not
+be very expensive and all operations on the generic objects probably have
+to be defined anyways.
+
 Resolution Scope
 ----------------
@@ -534,5 +596,6 @@
 Stack allocated functions interact badly with this because they are not
 static. There are several ways to try to resolve this, however without a
-general solution most can only buy time.
+general solution most can keep vtables from making the existing thunk problem
+worse, they don't do anything to solve it.
 
 Filling in some fields of a static vtable could cause issues on a recursive
@@ -549,2 +612,53 @@
 shortest lifetime of a function assigned to it. However this still limits the
 lifetime "implicitly" and returns to the original problem with thunks.
+
+Odds And Ends
+-------------
+
+In addition to the main design there are a few extras that should be
+considered. They are not part of the core design but make the new uses fully
+featured.
+
+### Extension: Parent-Child Assertion
+For hierarchy types in regular traits, generic functions or generic structures
+we may want to be able to check parent-child relationships between two types
+given. For this we might have to add another primitive assertion. It would
+have the following form if declared in code:
+
+    trait is_parent_child(dtype Parent, dtype Child) { <built-in magic> }
+
+This assertion is satified if Parent is an ancestor of Child in a hierarchy.
+In other words Child can be statically cast to Parent. The cast from Parent
+to child would be dynamically checked as usual.
+
+However in this form there are two concerns. The first that Parent will
+usually be consistent for a given use, it will not be a variable. Second is
+that we may also need the assertion functions. To do any casting/conversions
+anyways.
+TODO: Talk about when we wrap a concrete type and how that leads to "may".
+
+To this end it may be better that the parent trait combines the usual
+assertions plus this new primitive assertion. There may or may not be use
+cases for accessing just one half and providing easy access to them may be
+required depending on how that turns out.
+
+    trait Parent(dtype T | interface(T)) virtual(<grand-parent?>) { }
+
+### Extension: sizeof Compatablity
+Trait types are always sized, it may even be a fixed size like how pointers
+have the same size regardless of what they point at. However their contents
+may or may not be of a known size (if the `sized(...)` assertion is used).
+
+Currently there is no way to access this information. If it is needed a
+special syntax would have to be added. Here a special case of `sizeof` is
+used.
+
+    struct line aLine;
+    trait drawable widget = aLine;
+
+    size_t x = sizeof(widget);
+    size_t y = sizeof(trait drawable);
+
+As usual `y`, size of the type, is the size of the local storage used to put
+the value into. The other case `x` checks the saved stored value in the
+virtual table and returns that.
Index: src/AST/Attribute.hpp
===================================================================
--- src/AST/Attribute.hpp	(revision 9e1d48503286c2f21bf3f599590920efc8b02293)
+++ src/AST/Attribute.hpp	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
@@ -19,4 +19,5 @@
 #include <vector>
 
+#include "Fwd.hpp"
 #include "Node.hpp"     // for ptr
 #include "Visitor.hpp"
@@ -31,6 +32,7 @@
 	std::vector<ptr<Expr>> parameters;
 
-	Attribute( const std::string& name = "", std::vector<ptr<Expr>>&& params = {})
+	Attribute( const std::string & name = "", std::vector<ptr<Expr>> && params = {})
 	: name( name ), parameters( params ) {}
+	virtual ~Attribute() = default;
 
 	bool empty() const { return name.empty(); }
@@ -42,7 +44,11 @@
 	bool isValidOnFuncParam() const;
 
-	Attribute* accept( Visitor& v ) override { return v.visit( this ); }
+	const Attribute * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
-	Attribute* clone() const override { return new Attribute{ *this }; }
+	Attribute * clone() const override { return new Attribute{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 };
 
Index: src/AST/CVQualifiers.hpp
===================================================================
--- src/AST/CVQualifiers.hpp	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
+++ src/AST/CVQualifiers.hpp	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
@@ -0,0 +1,85 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// CVQualifiers.hpp --
+//
+// Author           : Aaron B. Moss
+// Created On       : Mon May 13 15:00:00 2019
+// Last Modified By : Aaron B. Moss
+// Last Modified On : Mon May 13 15:00:00 2019
+// Update Count     : 1
+//
+
+#pragma once
+
+#include "Bitfield.hpp"
+
+namespace ast {
+
+namespace CV {
+
+	/// Bitflags for qualifiers
+	enum {
+		Const    = 1 << 0,
+		Restrict = 1 << 1,
+		Volatile = 1 << 2,
+		Lvalue   = 1 << 3,
+		Mutex    = 1 << 4,
+		Atomic   = 1 << 5,
+		NumQualifiers = 6
+	};
+
+	/// Mask for equivalence-preserving qualfiers
+	enum { EquivQualifiers = ~(Restrict | Lvalue) };
+
+	/// Underlying data for qualifiers
+	struct qualifier_flags {
+		union {
+			unsigned int val;
+			struct {
+				bool is_const    : 1;
+				bool is_restrict : 1;
+				bool is_volatile : 1;
+				bool is_lvalue   : 1;
+				bool is_mutex    : 1;
+				bool is_atomic   : 1;
+			};
+		};
+
+		constexpr qualifier_flags( unsigned int val = 0 ) : val(val) {}
+	};
+
+	/// Type qualifiers
+	using Qualifiers = bitfield<qualifier_flags>;
+
+	// `restrict` and `lvalue` are ignored by qualifier equivalence.
+	// ordering is a subtype relationship over qualifiers, e.g. `int` => `const int` is free
+
+	bool operator== ( Qualifiers a, Qualifiers b ) {
+		return (a & EquivQualifiers) == (b & EquivQualifiers);
+	}
+	bool operator!= ( Qualifiers a, Qualifiers b ) {
+		return (a & EquivQualifiers) != (b & EquivQualifiers);
+	}
+	bool operator<= ( Qualifiers a, Qualifiers b ) {
+		return a.is_const    <= b.is_const    // non-const converts to const for free
+			&& a.is_volatile <= b.is_volatile // non-volatile converts to volatile for free
+			&& a.is_mutex    >= b.is_mutex    // mutex converts to non-mutex for free
+			&& a.is_atomic   == b.is_atomic;  // atomicity must be preserved in free conversion
+	}
+	bool operator<  ( Qualifiers a, Qualifiers b ) { return a != b && a <= b; }
+	bool operator>= ( Qualifiers a, Qualifiers b ) { return b <= a; }
+	bool operator>  ( Qualifiers a, Qualifiers b ) { return b < a; }
+
+}
+
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/AST/Convert.cpp
===================================================================
--- src/AST/Convert.cpp	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
+++ src/AST/Convert.cpp	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
@@ -0,0 +1,612 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// Convert.cpp --
+//
+// Author           : Thierry Delisle
+// Created On       : Thu May 09 15::37::05 2019
+// Last Modified By :
+// Last Modified On :
+// Update Count     :
+//
+
+#include "Convert.hpp"
+
+#include "AST/Pass.hpp"
+
+#include "AST/Attribute.hpp"
+#include "AST/Decl.hpp"
+#include "AST/Expr.hpp"
+#include "AST/Init.hpp"
+#include "AST/Stmt.hpp"
+
+
+#include "SynTree/Attribute.h"
+#include "SynTree/Declaration.h"
+
+//================================================================================================
+// Utilities
+template<template <class...> class C>
+struct to {
+	template<typename T>
+	static auto from( T && v ) -> C< typename T::value_type > {
+		C< typename T::value_type > l;
+		std::move(std::begin(v), std::end(v), std::back_inserter(l));
+		return l;
+	}
+};
+
+//================================================================================================
+class ConverterNewToOld {
+public:
+	std::list< Declaration * > translationUnit;
+};
+
+std::list< Declaration * > convert( std::list< ast::ptr< ast::Decl > > & translationUnit ) {
+	ast::Pass<ConverterNewToOld> converter;
+	ast::accept_all(translationUnit, converter);
+	return converter.pass.translationUnit;
+}
+
+//================================================================================================
+
+#define ACCEPT_1(name, child, type) \
+	old->child->accept(*this); \
+	auto name = strict_dynamic_cast< ast::type * >( node );
+
+#define ACCEPT_N(name, child, type) \
+	std::vector< ast::ptr<ast::type> > name; \
+	name.reserve( old->child.size() ); \
+	for( auto a : old->child ) { \
+		a->accept( *this ); \
+		name.emplace_back( strict_dynamic_cast< ast::type * >(node) ); \
+	}
+
+class ConverterOldToNew : public Visitor {
+public:
+	ast::Decl * decl() {
+		return strict_dynamic_cast< ast::Decl * >( node );
+	}
+private:
+	ast::Node * node;
+
+	template<template <class...> class C>
+	C<ast::Label> make_labels(C<Label> olds) {
+		C<ast::Label> ret;
+		for(auto oldn : olds) {
+			auto old = &oldn; // to reuse the MACRO
+			ACCEPT_N(attr, attributes, Attribute)
+			ast::Label l(
+				{},
+				old->get_name(),
+				to<std::vector>::from( std::move( attr ) )
+			);
+			ret.push_back( l );
+		}
+		return ret;
+	}
+
+	virtual void visit( ObjectDecl * old ) override final {
+		ACCEPT_1(type, type, Type)
+		ACCEPT_1(init, init, Init)
+		ACCEPT_1(bitWd, bitfieldWidth, Expr)
+		ACCEPT_N(attr, attributes, Attribute)
+
+		auto decl = new ast::ObjectDecl(
+			old->location,
+			old->name,
+			type,
+			init,
+			{ old->get_storageClasses().val },
+			{ old->linkage.val },
+			bitWd,
+			std::move( attr ),
+			{ old->get_funcSpec().val }
+		);
+		decl->scopeLevel = old->scopeLevel;
+		decl->mangleName = old->mangleName;
+		decl->isDeleted  = old->isDeleted;
+		decl->uniqueId   = old->uniqueId;
+		decl->extension  = old->extension;
+
+		this->node = decl;
+	}
+
+	virtual void visit( FunctionDecl * ) override final {
+
+	}
+
+	virtual void visit( StructDecl * old ) override final {
+		ACCEPT_N(members, members, Decl)
+		ACCEPT_N(params, parameters, TypeDecl)
+		ACCEPT_1(parent, parent, AggregateDecl)
+		ACCEPT_N(attr, attributes, Attribute)
+
+		auto decl = new ast::StructDecl(
+			old->location,
+			old->name,
+			old->kind,
+			std::move( attr ),
+			{ old->linkage.val }
+		);
+		decl->parent = parent;
+		decl->body   = old->body;
+		decl->parameters = params;
+		decl->members    = members;
+		decl->extension  = old->extension;
+		decl->uniqueId   = old->uniqueId;
+		decl->storage    = { old->storageClasses.val };
+
+		this->node = decl;
+	}
+
+	virtual void visit( UnionDecl * old ) override final {
+		ACCEPT_N(members, members, Decl)
+		ACCEPT_N(params, parameters, TypeDecl)
+		ACCEPT_1(parent, parent, AggregateDecl)
+		ACCEPT_N(attr, attributes, Attribute)
+
+		auto decl = new ast::UnionDecl(
+			old->location,
+			old->name,
+			std::move( attr ),
+			{ old->linkage.val }
+		);
+		decl->parent = parent;
+		decl->body   = old->body;
+		decl->parameters = params;
+		decl->members    = members;
+		decl->extension  = old->extension;
+		decl->uniqueId   = old->uniqueId;
+		decl->storage    = { old->storageClasses.val };
+
+		this->node = decl;
+	}
+
+	virtual void visit( EnumDecl * old ) override final {
+		ACCEPT_N(members, members, Decl)
+		ACCEPT_N(params, parameters, TypeDecl)
+		ACCEPT_1(parent, parent, AggregateDecl)
+		ACCEPT_N(attr, attributes, Attribute)
+
+		auto decl = new ast::UnionDecl(
+			old->location,
+			old->name,
+			std::move( attr ),
+			{ old->linkage.val }
+		);
+		decl->parent = parent;
+		decl->body   = old->body;
+		decl->parameters = params;
+		decl->members    = members;
+		decl->extension  = old->extension;
+		decl->uniqueId   = old->uniqueId;
+		decl->storage    = { old->storageClasses.val };
+
+		this->node = decl;
+	}
+
+	virtual void visit( TraitDecl * old ) override final {
+		ACCEPT_N(members, members, Decl)
+		ACCEPT_N(params, parameters, TypeDecl)
+		ACCEPT_1(parent, parent, AggregateDecl)
+		ACCEPT_N(attr, attributes, Attribute)
+
+		auto decl = new ast::UnionDecl(
+			old->location,
+			old->name,
+			std::move( attr ),
+			{ old->linkage.val }
+		);
+		decl->parent = parent;
+		decl->body   = old->body;
+		decl->parameters = params;
+		decl->members    = members;
+		decl->extension  = old->extension;
+		decl->uniqueId   = old->uniqueId;
+		decl->storage    = { old->storageClasses.val };
+
+		this->node = decl;
+	}
+
+	virtual void visit( TypeDecl * ) override final {
+
+	}
+
+	virtual void visit( TypedefDecl * old ) override final {
+		ACCEPT_1(type, base, Type)
+		ACCEPT_N(params, parameters, TypeDecl)
+		ACCEPT_N(asserts, assertions, DeclWithType)
+		auto decl = new ast::TypedefDecl(
+			old->location,
+			old->name,
+			{ old->storageClasses.val },
+			type,
+			{ old->linkage.val }
+		);
+
+		decl->assertions = asserts;
+		decl->parameters = params;
+		decl->extension  = old->extension;
+		decl->uniqueId   = old->uniqueId;
+		decl->storage    = { old->storageClasses.val };
+
+		this->node = decl;
+	}
+
+	virtual void visit( AsmDecl * ) override final {
+
+	}
+
+	virtual void visit( StaticAssertDecl * ) override final {
+
+	}
+
+	virtual void visit( CompoundStmt * old ) override final {
+		ACCEPT_N(kids, kids, Stmt)
+		auto stmt = new ast::CompoundStmt(
+			old->location,
+			to<std::list>::from( std::move(kids) )
+		);
+		stmt->labels = to<std::vector>::from( make_labels( std::move( old->labels ) ) );
+
+		this->node = stmt;
+	}
+
+	virtual void visit( ExprStmt * old ) override final {
+		ACCEPT_1(expr, expr, Expr)
+		auto stmt = new ast::ExprStmt(
+			old->location,
+			expr
+		);
+		stmt->labels = to<std::vector>::from( make_labels( std::move( old->labels ) ) );
+
+		this->node = stmt;
+	}
+
+	virtual void visit( AsmStmt * ) override final {
+
+	}
+
+	virtual void visit( DirectiveStmt * ) override final {
+
+	}
+
+	virtual void visit( IfStmt * ) override final {
+
+	}
+
+	virtual void visit( WhileStmt * ) override final {
+
+	}
+
+	virtual void visit( ForStmt * ) override final {
+
+	}
+
+	virtual void visit( SwitchStmt * ) override final {
+
+	}
+
+	virtual void visit( CaseStmt * ) override final {
+
+	}
+
+	virtual void visit( BranchStmt * ) override final {
+
+	}
+
+	virtual void visit( ReturnStmt * ) override final {
+
+	}
+
+	virtual void visit( ThrowStmt * ) override final {
+
+	}
+
+	virtual void visit( TryStmt * ) override final {
+
+	}
+
+	virtual void visit( CatchStmt * ) override final {
+
+	}
+
+	virtual void visit( FinallyStmt * ) override final {
+
+	}
+
+	virtual void visit( WaitForStmt * ) override final {
+
+	}
+
+	virtual void visit( WithStmt * ) override final {
+
+	}
+
+	virtual void visit( NullStmt * old ) override final {
+		auto stmt = new ast::NullStmt(
+			old->location,
+			to<std::vector>::from( make_labels( std::move( old->labels ) ) )
+		);
+
+		this->node = stmt;
+	}
+
+	virtual void visit( DeclStmt * ) override final {
+
+	}
+
+	virtual void visit( ImplicitCtorDtorStmt * ) override final {
+
+	}
+
+	virtual void visit( ApplicationExpr * ) override final {
+
+	}
+
+	virtual void visit( UntypedExpr * ) override final {
+
+	}
+
+	virtual void visit( NameExpr * ) override final {
+
+	}
+
+	virtual void visit( CastExpr * ) override final {
+
+	}
+
+	virtual void visit( KeywordCastExpr * ) override final {
+
+	}
+
+	virtual void visit( VirtualCastExpr * ) override final {
+
+	}
+
+	virtual void visit( AddressExpr * ) override final {
+
+	}
+
+	virtual void visit( LabelAddressExpr * ) override final {
+
+	}
+
+	virtual void visit( UntypedMemberExpr * ) override final {
+
+	}
+
+	virtual void visit( MemberExpr * ) override final {
+
+	}
+
+	virtual void visit( VariableExpr * ) override final {
+
+	}
+
+	virtual void visit( ConstantExpr * ) override final {
+
+	}
+
+	virtual void visit( SizeofExpr * ) override final {
+
+	}
+
+	virtual void visit( AlignofExpr * ) override final {
+
+	}
+
+	virtual void visit( UntypedOffsetofExpr * ) override final {
+
+	}
+
+	virtual void visit( OffsetofExpr * ) override final {
+
+	}
+
+	virtual void visit( OffsetPackExpr * ) override final {
+
+	}
+
+	virtual void visit( AttrExpr * ) override final {
+
+	}
+
+	virtual void visit( LogicalExpr * ) override final {
+
+	}
+
+	virtual void visit( ConditionalExpr * ) override final {
+
+	}
+
+	virtual void visit( CommaExpr * ) override final {
+
+	}
+
+	virtual void visit( TypeExpr * ) override final {
+
+	}
+
+	virtual void visit( AsmExpr * ) override final {
+
+	}
+
+	virtual void visit( ImplicitCopyCtorExpr * ) override final {
+
+	}
+
+	virtual void visit( ConstructorExpr *  ) override final {
+
+	}
+
+	virtual void visit( CompoundLiteralExpr * ) override final {
+
+	}
+
+	virtual void visit( RangeExpr * ) override final {
+
+	}
+
+	virtual void visit( UntypedTupleExpr * ) override final {
+
+	}
+
+	virtual void visit( TupleExpr * ) override final {
+
+	}
+
+	virtual void visit( TupleIndexExpr * ) override final {
+
+	}
+
+	virtual void visit( TupleAssignExpr * ) override final {
+
+	}
+
+	virtual void visit( StmtExpr *  ) override final {
+
+	}
+
+	virtual void visit( UniqueExpr *  ) override final {
+
+	}
+
+	virtual void visit( UntypedInitExpr *  ) override final {
+
+	}
+
+	virtual void visit( InitExpr *  ) override final {
+
+	}
+
+	virtual void visit( DeletedExpr * ) override final {
+
+	}
+
+	virtual void visit( DefaultArgExpr * ) override final {
+
+	}
+
+	virtual void visit( GenericExpr * ) override final {
+
+	}
+
+	virtual void visit( VoidType * ) override final {
+
+	}
+
+	virtual void visit( BasicType * ) override final {
+
+	}
+
+	virtual void visit( PointerType * ) override final {
+
+	}
+
+	virtual void visit( ArrayType * ) override final {
+
+	}
+
+	virtual void visit( ReferenceType * ) override final {
+
+	}
+
+	virtual void visit( QualifiedType * ) override final {
+
+	}
+
+	virtual void visit( FunctionType * ) override final {
+
+	}
+
+	virtual void visit( StructInstType * ) override final {
+
+	}
+
+	virtual void visit( UnionInstType * ) override final {
+
+	}
+
+	virtual void visit( EnumInstType * ) override final {
+
+	}
+
+	virtual void visit( TraitInstType * ) override final {
+
+	}
+
+	virtual void visit( TypeInstType * ) override final {
+
+	}
+
+	virtual void visit( TupleType * ) override final {
+
+	}
+
+	virtual void visit( TypeofType * ) override final {
+
+	}
+
+	virtual void visit( AttrType * ) override final {
+
+	}
+
+	virtual void visit( VarArgsType * ) override final {
+
+	}
+
+	virtual void visit( ZeroType * ) override final {
+
+	}
+
+	virtual void visit( OneType * ) override final {
+
+	}
+
+	virtual void visit( GlobalScopeType * ) override final {
+
+	}
+
+	virtual void visit( Designation * ) override final {
+
+	}
+
+	virtual void visit( SingleInit * ) override final {
+
+	}
+
+	virtual void visit( ListInit * ) override final {
+
+	}
+
+	virtual void visit( ConstructorInit * ) override final {
+
+	}
+
+	virtual void visit( Constant * ) override final {
+
+	}
+
+	virtual void visit( Attribute * ) override final {
+
+	}
+};
+
+#undef ACCEPT_N
+#undef ACCEPT_1
+
+std::list< ast::ptr< ast::Decl > > convert( const std::list< Declaration * > & translationUnit ) {
+	ConverterOldToNew c;
+	std::list< ast::ptr< ast::Decl > > decls;
+	for(auto d : translationUnit) {
+		d->accept( c );
+		decls.emplace_back( c.decl() );
+		delete d;
+	}
+	return decls;
+}
Index: src/AST/Convert.hpp
===================================================================
--- src/AST/Convert.hpp	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
+++ src/AST/Convert.hpp	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
@@ -0,0 +1,28 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// Convert.hpp --
+//
+// Author           : Thierry Delisle
+// Created On       : Thu May 09 15::37::05 2019
+// Last Modified By :
+// Last Modified On :
+// Update Count     :
+//
+
+#pragma once
+
+#include <list>
+
+#include "AST/Node.hpp"
+
+class Declaration;
+namespace ast {
+	class Decl;
+};
+
+std::list< Declaration * > convert( const std::list< ast::ptr< ast::Decl > > & translationUnit );
+std::list< ast::ptr< ast::Decl > > convert( const std::list< Declaration * > & translationUnit );
Index: src/AST/Decl.hpp
===================================================================
--- src/AST/Decl.hpp	(revision 9e1d48503286c2f21bf3f599590920efc8b02293)
+++ src/AST/Decl.hpp	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
@@ -57,7 +57,7 @@
 	static readonly<Decl> fromId( UniqueId id );
 
-	virtual Decl* accept( Visitor& v ) override = 0;
-private:
-	virtual Decl* clone() const override = 0;
+	virtual const Decl * accept( Visitor & v ) const override = 0;
+private:
+	virtual Decl * clone() const override = 0;
 };
 
@@ -85,11 +85,11 @@
 
 	/// Get type of this declaration. May be generated by subclass
-	virtual const Type* get_type() const = 0;
+	virtual const Type * get_type() const = 0;
 	/// Set type of this declaration. May be verified by subclass
 	virtual void set_type(Type*) = 0;
 
-	virtual DeclWithType* accept( Visitor& v ) override = 0;
-private:
-	virtual DeclWithType* clone() const override = 0;
+	virtual const DeclWithType * accept( Visitor & v ) const override = 0;
+private:
+	virtual DeclWithType * clone() const override = 0;
 };
 
@@ -110,7 +110,11 @@
 	void set_type( Type* ty ) override { type = ty; }
 
-	DeclWithType* accept( Visitor& v ) override { return v.visit( this ); }
-private:
-	ObjectDecl* clone() const override { return new ObjectDecl{ *this }; }
+	virtual const DeclWithType * accept( Visitor& v ) const override { return v.visit( this ); }
+private:
+	virtual 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);
 };
 
@@ -169,7 +173,7 @@
 	bool isComplete() { return sized; }
 
-	Decl* accept( Visitor& v ) override { return v.visit( this ); }
-private:
-	TypeDecl* clone() const override { return new TypeDecl{ *this }; }
+	virtual const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	virtual TypeDecl * clone() const override { return new TypeDecl{ *this }; }
 };
 
@@ -183,7 +187,7 @@
 	std::string typeString() const override { return "typedef"; }
 
-	Decl* accept( Visitor& v ) override { return v.visit( this ); }
-private:
-	TypedefDecl* clone() const override { return new TypedefDecl{ *this }; }
+	virtual const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	virtual TypedefDecl * clone() const override { return new TypedefDecl{ *this }; }
 };
 
@@ -223,7 +227,7 @@
 	bool is_thread() { return kind == DeclarationNode::Thread; }
 
-	Decl* accept( Visitor& v ) override { return v.visit( this ); }
-private:
-	StructDecl* clone() const override { return new StructDecl{ *this }; }
+	virtual const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	virtual StructDecl * clone() const override { return new StructDecl{ *this }; }
 
 	std::string typeString() const override { return "struct"; }
@@ -237,7 +241,7 @@
 	: AggregateDecl( loc, name, std::move(attrs), linkage ) {}
 
-	Decl* accept( Visitor& v ) override { return v.visit( this ); }
-private:
-	UnionDecl* clone() const override { return new UnionDecl{ *this }; }
+	virtual const Decl * accept( Visitor& v ) const override { return v.visit( this ); }
+private:
+	virtual UnionDecl * clone() const override { return new UnionDecl{ *this }; }
 
 	std::string typeString() const override { return "union"; }
@@ -254,7 +258,7 @@
 	bool valueOf( Decl* enumerator, long long& value ) const;
 
-	Decl* accept( Visitor& v ) override { return v.visit( this ); }
-private:
-	EnumDecl* clone() const override { return new EnumDecl{ *this }; }
+	virtual const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	virtual EnumDecl * clone() const override { return new EnumDecl{ *this }; }
 
 	std::string typeString() const override { return "enum"; }
@@ -271,7 +275,7 @@
 	: AggregateDecl( loc, name, std::move(attrs), linkage ) {}
 
-	Decl* accept( Visitor& v ) override { return v.visit( this ); }
-private:
-	TraitDecl* clone() const override { return new TraitDecl{ *this }; }
+	virtual const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	virtual TraitDecl * clone() const override { return new TraitDecl{ *this }; }
 
 	std::string typeString() const override { return "trait"; }
@@ -290,6 +294,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); }
@@ -306,14 +310,14 @@
 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 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 9e1d48503286c2f21bf3f599590920efc8b02293)
+++ src/AST/Expr.hpp	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
@@ -27,5 +27,5 @@
 namespace ast {
 
-/// Contains the ID of a declaration and a type that is derived from that declaration, 
+/// Contains the ID of a declaration and a type that is derived from that declaration,
 /// but subject to decay-to-pointer and type parameter renaming
 struct ParamEntry {
@@ -74,5 +74,5 @@
 			case Empty:  return;
 			case Slots:  new(&data.resnSlots) ResnSlots{ std::move(o.data.resnSlots) }; return;
-			case Params: 
+			case Params:
 				new(&data.inferParams) InferredParams{ std::move(o.data.inferParams) }; return;
 			}
@@ -121,5 +121,5 @@
 	Expr * set_extension( bool ex ) { extension = ex; return this; }
 
-	virtual Expr * accept( Visitor & v ) override = 0;
+	virtual const Expr * accept( Visitor & v ) const override = 0;
 private:
 	virtual Expr * clone() const override = 0;
@@ -133,9 +133,95 @@
 	TypeExpr( const CodeLocation & loc, const Type * t ) : Expr(loc), type(t) {}
 
-	Expr * accept( Visitor & v ) override { return v.visit( this ); }
+	const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
 	TypeExpr * clone() const override { return new TypeExpr{ *this }; }
 };
 
+
+//=================================================================================================
+/// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency
+/// remove only if there is a better solution
+/// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with
+/// forward declarations
+inline void increment( const class Expr * node, Node::ref_type ref ) { node->increment(ref); }
+inline void decrement( const class Expr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class ApplicationExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class ApplicationExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class UntypedExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class UntypedExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class NameExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class NameExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class AddressExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class AddressExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class LabelAddressExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class LabelAddressExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class CastExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class CastExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class KeywordCastExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class KeywordCastExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class VirtualCastExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class VirtualCastExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class MemberExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class MemberExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class UntypedMemberExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class UntypedMemberExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class VariableExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class VariableExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class ConstantExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class ConstantExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class SizeofExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class SizeofExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class AlignofExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class AlignofExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class UntypedOffsetofExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class UntypedOffsetofExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class OffsetofExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class OffsetofExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class OffsetPackExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class OffsetPackExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class AttrExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class AttrExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class LogicalExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class LogicalExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class ConditionalExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class ConditionalExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class CommaExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class CommaExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class TypeExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class TypeExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class AsmExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class AsmExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class ImplicitCopyCtorExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class ImplicitCopyCtorExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class ConstructorExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class ConstructorExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class CompoundLiteralExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class CompoundLiteralExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class UntypedValofExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class UntypedValofExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class RangeExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class RangeExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class UntypedTupleExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class UntypedTupleExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class TupleExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class TupleExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class TupleIndexExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class TupleIndexExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class TupleAssignExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class TupleAssignExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class StmtExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class StmtExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class UniqueExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class UniqueExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class UntypedInitExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class UntypedInitExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class InitExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class InitExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class DeletedExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class DeletedExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class DefaultArgExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class DefaultArgExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+// inline void increment( const class GenericExpr * node, Node::ref_type ref ) { node->increment(ref); }
+// inline void decrement( const class GenericExpr * node, Node::ref_type ref ) { node->decrement(ref); }
 }
 
Index: src/AST/Fwd.hpp
===================================================================
--- src/AST/Fwd.hpp	(revision 9e1d48503286c2f21bf3f599590920efc8b02293)
+++ src/AST/Fwd.hpp	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
@@ -136,4 +136,6 @@
 
 class TypeSubstitution;
+
+std::string toString( const Node * );
 
 //=================================================================================================
@@ -352,6 +354,4 @@
 inline void increment( const class Constant *, Node::ref_type );
 inline void decrement( const class Constant *, Node::ref_type );
-inline void increment( const class Label *, Node::ref_type );
-inline void decrement( const class Label *, Node::ref_type );
 inline void increment( const class Attribute *, Node::ref_type );
 inline void decrement( const class Attribute *, Node::ref_type );
Index: src/AST/Init.hpp
===================================================================
--- src/AST/Init.hpp	(revision 9e1d48503286c2f21bf3f599590920efc8b02293)
+++ src/AST/Init.hpp	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
@@ -37,7 +37,7 @@
 	: ParseNode( loc ), designators( std::move(ds) ) {}
 
-	Designation* accept( Visitor& v ) override { return v.visit( this ); }
+	virtual const Designation* accept( Visitor& v ) const override { return v.visit( this ); }
 private:
-	Designation* clone() const override { return new Designation{ *this }; }
+	virtual Designation* clone() const override { return new Designation{ *this }; }
 };
 
@@ -52,7 +52,7 @@
 	Init( const CodeLocation& loc, ConstructFlag mc ) : ParseNode( loc ), maybeConstructed( mc ) {}
 
-	virtual Init* accept( Visitor& v ) override = 0;
+	virtual const Init * accept( Visitor& v ) const override = 0;
 private:
-	virtual Init* clone() const override = 0;
+	virtual const Init * clone() const override = 0;
 };
 
@@ -66,7 +66,11 @@
 	: Init( loc, mc ), value( val ) {}
 
-	Init* accept( Visitor& v ) override { return v.visit( this ); }
+	virtual const Init * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
-	SingleInit* clone() const override { return new SingleInit{ *this }; }
+	virtual SingleInit * clone() const override { return new SingleInit{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 };
 
@@ -90,7 +94,11 @@
 	const_iterator end() const { return initializers.end(); }
 
-	Init* accept( Visitor& v ) override { return v.visit( this ); }
+	virtual const Init * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
-	ListInit* clone() const override { return new ListInit{ *this }; }
+	virtual ListInit * clone() const override { return new ListInit{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 };
 
@@ -109,7 +117,11 @@
 	: Init( loc, DoConstruct ), ctor( ctor ), dtor( dtor ), init( init ) {}
 
-	Init* accept( Visitor& v ) override { return v.visit( this ); }
+	virtual const Init * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
-	ConstructorInit* clone() const override { return new ConstructorInit{ *this }; }
+	virtual ConstructorInit * clone() const override { return new ConstructorInit{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 };
 
Index: src/AST/Label.hpp
===================================================================
--- src/AST/Label.hpp	(revision 9e1d48503286c2f21bf3f599590920efc8b02293)
+++ src/AST/Label.hpp	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
@@ -35,5 +35,5 @@
 
 	Label( CodeLocation loc, const std::string& name = "",
-		const std::vector<ptr<Attribute>>& attrs = std::vector<ptr<Attribute>>{} )
+		std::vector<ptr<Attribute>> && attrs = std::vector<ptr<Attribute>>{} )
 	: location( loc ), name( name ), attributes( attrs ) {}
 
@@ -48,13 +48,4 @@
 inline std::ostream& operator<< ( std::ostream& out, const Label& l ) { return out << l.name; }
 
-
-//=================================================================================================
-/// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency
-/// remove only if there is a better solution
-/// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with
-/// forward declarations
-inline void increment( const class Label * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class Label * node, Node::ref_type ref ) { node->decrement( ref ); }
-
 }
 
Index: src/AST/Node.hpp
===================================================================
--- src/AST/Node.hpp	(revision 9e1d48503286c2f21bf3f599590920efc8b02293)
+++ src/AST/Node.hpp	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
@@ -30,11 +30,11 @@
 	// change/share reference counts
 	Node() = default;
-	Node(const Node&) : strong_ref(0), weak_ref(0) {}
-	Node(Node&&) : strong_ref(0), weak_ref(0) {}
+	Node(const Node&) : strong_count(0), weak_count(0) {}
+	Node(Node&&) : strong_count(0), weak_count(0) {}
 	Node& operator= (const Node&) = delete;
 	Node& operator= (Node&&) = delete;
 	virtual ~Node() = default;
 
-	virtual Node* accept( Visitor& v ) = 0;
+	virtual const Node * accept( Visitor & v ) const = 0;
 
 	/// Types of node references
@@ -46,6 +46,6 @@
 	inline void increment(ref_type ref) const {
 		switch (ref) {
-			case ref_type::strong: strong_ref++; break;
-			case ref_type::weak  : weak_ref  ++; break;
+			case ref_type::strong: strong_count++; break;
+			case ref_type::weak  : weak_count  ++; break;
 		}
 	}
@@ -53,22 +53,22 @@
 	inline void decrement(ref_type ref) const {
 		switch (ref) {
-			case ref_type::strong: strong_ref--; break;
-			case ref_type::weak  : weak_ref  --; break;
+			case ref_type::strong: strong_count--; break;
+			case ref_type::weak  : weak_count  --; break;
 		}
 
-		if(!strong_ref && !weak_ref) {
+		if(!strong_count && !weak_count) {
 			delete this;
 		}
 	}
+private:
+	/// Make a copy of this node; should be overridden in subclass with more precise return type
+	virtual const Node * clone() const = 0;
 
+	/// Must be copied in ALL derived classes
 	template<typename node_t>
 	friend auto mutate(const node_t * node);
 
-private:
-	/// Make a copy of this node; should be overridden in subclass with more precise return type
-	virtual Node* clone() const = 0;
-
-	mutable size_t strong_ref = 0;
-	mutable size_t weak_ref = 0;
+	mutable size_t strong_count = 0;
+	mutable size_t weak_count = 0;
 };
 
@@ -100,15 +100,21 @@
 public:
 	ptr_base() : node(nullptr) {}
-	ptr_base( const node_t * n ) : node(n) { if( node ) node->increment(ref_t); }
-	~ptr_base() { if( node ) node->decrement(ref_t); }
+	ptr_base( const node_t * n ) : node(n) { if( node ) increment(node, ref_t); }
+	~ptr_base() { if( node ) decrement(node, ref_t); }
 
 	template< enum Node::ref_type o_ref_t >
 	ptr_base( const ptr_base<node_t, o_ref_t> & o ) : node(o.node) {
-		if( node ) node->increment(ref_t);
+		if( node ) increment(node, ref_t);
 	}
 
 	template< enum Node::ref_type o_ref_t >
 	ptr_base( ptr_base<node_t, o_ref_t> && o ) : node(o.node) {
-		if( node ) node->increment(ref_t);
+		if( node ) increment(node, ref_t);
+	}
+
+	template<typename o_node_t>
+	ptr_base & operator=( const o_node_t * node ) {
+		assign(strict_dynamic_cast<const node_t *>(node));
+		return *this;
 	}
 
@@ -138,6 +144,6 @@
 private:
 	void assign( const node_t * other ) {
-		if( other ) other->increment(ref_t);
-		if( node  ) node ->decrement(ref_t);
+		if( other ) increment(other, ref_t);
+		if( node  ) decrement(node , ref_t);
 		node = other;
 	}
Index: src/AST/Pass.hpp
===================================================================
--- src/AST/Pass.hpp	(revision 9e1d48503286c2f21bf3f599590920efc8b02293)
+++ src/AST/Pass.hpp	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
@@ -23,5 +23,11 @@
 #include "AST/Fwd.hpp"
 #include "AST/Node.hpp"
+
+#include "AST/Attribute.hpp"
 #include "AST/Decl.hpp"
+#include "AST/Expr.hpp"
+#include "AST/Init.hpp"
+#include "AST/Stmt.hpp"
+
 #include "AST/Visitor.hpp"
 
@@ -79,97 +85,97 @@
 
 	/// Visit function declarations
-	virtual DeclWithType *     visit( const ObjectDecl           * ) override final;
-	virtual DeclWithType *     visit( const FunctionDecl         * ) override final;
-	virtual Decl *             visit( const StructDecl           * ) override final;
-	virtual Decl *             visit( const UnionDecl            * ) override final;
-	virtual Decl *             visit( const EnumDecl             * ) override final;
-	virtual Decl *             visit( const TraitDecl            * ) override final;
-	virtual Decl *             visit( const TypeDecl             * ) override final;
-	virtual Decl *             visit( const TypedefDecl          * ) override final;
-	virtual AsmDecl *          visit( const AsmDecl              * ) override final;
-	virtual StaticAssertDecl * visit( const StaticAssertDecl     * ) override final;
-	virtual CompoundStmt *     visit( const CompoundStmt         * ) override final;
-	virtual Stmt *             visit( const ExprStmt             * ) override final;
-	virtual Stmt *             visit( const AsmStmt              * ) override final;
-	virtual Stmt *             visit( const DirectiveStmt        * ) override final;
-	virtual Stmt *             visit( const IfStmt               * ) override final;
-	virtual Stmt *             visit( const WhileStmt            * ) override final;
-	virtual Stmt *             visit( const ForStmt              * ) override final;
-	virtual Stmt *             visit( const SwitchStmt           * ) override final;
-	virtual Stmt *             visit( const CaseStmt             * ) override final;
-	virtual Stmt *             visit( const BranchStmt           * ) override final;
-	virtual Stmt *             visit( const ReturnStmt           * ) override final;
-	virtual Stmt *             visit( const ThrowStmt            * ) override final;
-	virtual Stmt *             visit( const TryStmt              * ) override final;
-	virtual Stmt *             visit( const CatchStmt            * ) override final;
-	virtual Stmt *             visit( const FinallyStmt          * ) override final;
-	virtual Stmt *             visit( const WaitForStmt          * ) override final;
-	virtual Stmt *             visit( const WithStmt             * ) override final;
-	virtual NullStmt *         visit( const NullStmt             * ) override final;
-	virtual Stmt *             visit( const DeclStmt             * ) override final;
-	virtual Stmt *             visit( const ImplicitCtorDtorStmt * ) override final;
-	virtual Expr *             visit( const ApplicationExpr      * ) override final;
-	virtual Expr *             visit( const UntypedExpr          * ) override final;
-	virtual Expr *             visit( const NameExpr             * ) override final;
-	virtual Expr *             visit( const AddressExpr          * ) override final;
-	virtual Expr *             visit( const LabelAddressExpr     * ) override final;
-	virtual Expr *             visit( const CastExpr             * ) override final;
-	virtual Expr *             visit( const KeywordCastExpr      * ) override final;
-	virtual Expr *             visit( const VirtualCastExpr      * ) override final;
-	virtual Expr *             visit( const UntypedMemberExpr    * ) override final;
-	virtual Expr *             visit( const MemberExpr           * ) override final;
-	virtual Expr *             visit( const VariableExpr         * ) override final;
-	virtual Expr *             visit( const ConstantExpr         * ) override final;
-	virtual Expr *             visit( const SizeofExpr           * ) override final;
-	virtual Expr *             visit( const AlignofExpr          * ) override final;
-	virtual Expr *             visit( const UntypedOffsetofExpr  * ) override final;
-	virtual Expr *             visit( const OffsetofExpr         * ) override final;
-	virtual Expr *             visit( const OffsetPackExpr       * ) override final;
-	virtual Expr *             visit( const AttrExpr             * ) override final;
-	virtual Expr *             visit( const LogicalExpr          * ) override final;
-	virtual Expr *             visit( const ConditionalExpr      * ) override final;
-	virtual Expr *             visit( const CommaExpr            * ) override final;
-	virtual Expr *             visit( const TypeExpr             * ) override final;
-	virtual Expr *             visit( const AsmExpr              * ) override final;
-	virtual Expr *             visit( const ImplicitCopyCtorExpr * ) override final;
-	virtual Expr *             visit( const ConstructorExpr      * ) override final;
-	virtual Expr *             visit( const CompoundLiteralExpr  * ) override final;
-	virtual Expr *             visit( const RangeExpr            * ) override final;
-	virtual Expr *             visit( const UntypedTupleExpr     * ) override final;
-	virtual Expr *             visit( const TupleExpr            * ) override final;
-	virtual Expr *             visit( const TupleIndexExpr       * ) override final;
-	virtual Expr *             visit( const TupleAssignExpr      * ) override final;
-	virtual Expr *             visit( const StmtExpr             * ) override final;
-	virtual Expr *             visit( const UniqueExpr           * ) override final;
-	virtual Expr *             visit( const UntypedInitExpr      * ) override final;
-	virtual Expr *             visit( const InitExpr             * ) override final;
-	virtual Expr *             visit( const DeletedExpr          * ) override final;
-	virtual Expr *             visit( const DefaultArgExpr       * ) override final;
-	virtual Expr *             visit( const GenericExpr          * ) override final;
-	virtual Type *             visit( const VoidType             * ) override final;
-	virtual Type *             visit( const BasicType            * ) override final;
-	virtual Type *             visit( const PointerType          * ) override final;
-	virtual Type *             visit( const ArrayType            * ) override final;
-	virtual Type *             visit( const ReferenceType        * ) override final;
-	virtual Type *             visit( const QualifiedType        * ) override final;
-	virtual Type *             visit( const FunctionType         * ) override final;
-	virtual Type *             visit( const StructInstType       * ) override final;
-	virtual Type *             visit( const UnionInstType        * ) override final;
-	virtual Type *             visit( const EnumInstType         * ) override final;
-	virtual Type *             visit( const TraitInstType        * ) override final;
-	virtual Type *             visit( const TypeInstType         * ) override final;
-	virtual Type *             visit( const TupleType            * ) override final;
-	virtual Type *             visit( const TypeofType           * ) override final;
-	virtual Type *             visit( const VarArgsType          * ) override final;
-	virtual Type *             visit( const ZeroType             * ) override final;
-	virtual Type *             visit( const OneType              * ) override final;
-	virtual Type *             visit( const GlobalScopeType      * ) override final;
-	virtual Designation *      visit( const Designation          * ) override final;
-	virtual Init *             visit( const SingleInit           * ) override final;
-	virtual Init *             visit( const ListInit             * ) override final;
-	virtual Init *             visit( const ConstructorInit      * ) override final;
-	virtual Constant *         visit( const Constant             * ) override final;
-	virtual Attribute *        visit( const Attribute            * ) override final;
-	virtual TypeSubstitution * visit( const TypeSubstitution     * ) override final;
+	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;
 
 	friend void acceptAll( std::list< ptr<Decl> > & decls, Pass<pass_t>& visitor );
@@ -179,16 +185,19 @@
 
 private:
+	const ast::Stmt * call_accept( const ast::Stmt * );
+	const ast::Expr * call_accept( const ast::Expr * );
+
+	template< typename node_t >
+	auto call_accept( const node_t * node ) -> decltype( node->accept(*this) );
+
+	template< template <class...> class container_t >
+	container_t< ptr<Stmt> > call_accept( const container_t< ptr<Stmt> > & );
+
+	template< template <class...> class container_t, typename node_t >
+	container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container );
+
 	/// Logic to call the accept and mutate the parent if needed, delegates call to accept
-	template<typename parent_t, typename child_t>
-	void maybe_accept(parent_t * & , typename parent_t::child_t *);
-
-	Stmt * call_accept( const Stmt * );
-	Expr * call_accept( const Expr * );
-
-	template< template <class> class container_t >
-	container_t< ptr<Stmt> > call_accept( const container_t< ptr<Stmt> > & );
-
-	template< template <class> class container_t, typename node_t >
-	container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container );
+	template<typename node_t, typename parent_t, typename child_t>
+	void maybe_accept(const node_t * &, child_t parent_t::* child);
 
 private:
@@ -209,5 +218,5 @@
 
 template<typename pass_t>
-void acceptAll( std::list< ptr<Decl> >, Pass<pass_t>& visitor );
+void accept_all( std::list< ast::ptr<ast::Decl> > &, ast::Pass<pass_t> & visitor );
 
 //-------------------------------------------------------------------------------------------------
@@ -215,7 +224,4 @@
 //-------------------------------------------------------------------------------------------------
 
-template<typename T>
-using std_list = std::list<T>;
-
 /// Keep track of the polymorphic const TypeSubstitution * env for the current expression
 struct WithConstTypeSubstitution {
@@ -225,5 +231,5 @@
 /// Used if visitor requires added statements before or after the current node.
 /// The Pass template handles what *before* and *after* means automatically
-template< template<class> class container_t = std_list >
+template< template<class...> class container_t = std::list >
 struct WithStmtsToAdd {
 	container_t< ptr<Stmt> > stmtsToAddBefore;
@@ -233,5 +239,5 @@
 /// Used if visitor requires added declarations before or after the current node.
 /// The Pass template handles what *before* and *after* means automatically
-template< template<class> class container_t = std_list >
+template< template<class...> class container_t = std::list >
 struct WithDeclsToAdd {
 	container_t< ptr<Decl> > declsToAddBefore;
@@ -285,2 +291,12 @@
 };
 }
+
+#include "Common/Stats.h"
+
+extern struct PassVisitorStats {
+	size_t depth = 0;
+	Stats::Counters::MaxCounter<double> * max = nullptr;
+	Stats::Counters::AverageCounter<double> * avg = nullptr;
+} pass_visitor_stats;
+
+#include "AST/Pass.impl.hpp"
Index: src/AST/Pass.impl.hpp
===================================================================
--- src/AST/Pass.impl.hpp	(revision 9e1d48503286c2f21bf3f599590920efc8b02293)
+++ src/AST/Pass.impl.hpp	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
@@ -16,4 +16,7 @@
 #pragma once
 // IWYU pragma: private, include "AST/Pass.hpp"
+
+#include <type_traits>
+#include <unordered_map>
 
 #define VISIT_START( node ) \
@@ -26,5 +29,5 @@
 	__pass::previsit( pass, node, 0 );
 
-#define VISIT( code ) \
+#define VISIT( code... ) \
 	/* if this node should visit its children */ \
 	if ( __visit_children() ) { \
@@ -35,13 +38,13 @@
 #define VISIT_END( type, node ) \
 	/* call the implementation of the postvisit of this pass */ \
-	auto __return = __pass::postvisit< type * >( node ); \
+	auto __return = __pass::postvisit( pass, node, 0 ); \
 	assertf(__return, "post visit should never return null"); \
 	return __return;
 
 #ifdef PEDANTIC_PASS_ASSERT
-#define __pedantic_pass_assert (...) assert (__VAR_ARGS__)
-#define __pedantic_pass_assertf(...) assertf(__VAR_ARGS__)
+#define __pedantic_pass_assert(...) assert (__VA_ARGS__)
+#define __pedantic_pass_assertf(...) assertf(__VA_ARGS__)
 #else
-#define __pedantic_pass_assert (...)
+#define __pedantic_pass_assert(...)
 #define __pedantic_pass_assertf(...)
 #endif
@@ -55,9 +58,10 @@
 		}
 
-		template<typename it_t, template <class> class container_t>
-		static inline void take_all( it_t it, container_t<ast::ptr<ast::Declaration>> * decls, bool * mutated = nullptr ) {
+		//------------------------------
+		template<typename it_t, template <class...> class container_t>
+		static inline void take_all( it_t it, container_t<ast::ptr<ast::Decl>> * decls, bool * mutated = nullptr ) {
 			if(empty(decls)) return;
 
-			std::transform(decls->begin(), decls->end(), it, [](Declaration * decl) -> auto {
+			std::transform(decls->begin(), decls->end(), it, [](const ast::Decl * decl) -> auto {
 					return new DeclStmt( decl );
 				});
@@ -66,6 +70,6 @@
 		}
 
-		template<typename it_t, template <class> class container_t>
-		static inline void take_all( it_t it, container_t<ast::ptr<ast::Statement>> * decls, bool * mutated = nullptr ) {
+		template<typename it_t, template <class...> class container_t>
+		static inline void take_all( it_t it, container_t<ast::ptr<ast::Stmt>> * decls, bool * mutated = nullptr ) {
 			if(empty(decls)) return;
 
@@ -75,30 +79,39 @@
 		}
 
+		//------------------------------
+		/// Check if should be skipped, different for pointers and containers
 		template<typename node_t>
-		bool differs( const node_t * old_val, const node_t * new_val ) {
+		bool skip( const ast::ptr<node_t> & val) {
+			return !val;
+		}
+
+		template< template <class...> class container_t, typename node_t >
+		bool skip( const container_t<ast::ptr< node_t >> & val ) {
+			return val.empty();
+		}
+
+		//------------------------------
+		/// Get the value to visit, different for pointers and containers
+		template<typename node_t>
+		auto get( const ast::ptr<node_t> & val, int ) -> decltype(val.get()) {
+			return val.get();
+		}
+
+		template<typename node_t>
+		const node_t & get( const node_t & val, long) {
+			return val;
+		}
+
+
+		//------------------------------
+		/// Check if value was mutated, different for pointers and containers
+		template<typename lhs_t, typename rhs_t>
+		bool differs( const lhs_t * old_val, const rhs_t * new_val ) {
 			return old_val != new_val;
 		}
 
-		template< template <class> class container_t >
-		bool differs( const container_t<ast::ptr< ast::Statement >> &, const container_t<ast::ptr< ast::Statement >> & new_val ) {
+		template< template <class...> class container_t, typename node_t >
+		bool differs( const container_t<ast::ptr< node_t >> &, const container_t<ast::ptr< node_t >> & new_val ) {
 			return !new_val.empty();
-		}
-	}
-
-	template<typename parent_t, typename child_t>
-	template< typename pass_t >
-	void Pass< pass_t >::maybe_accept(
-		const parent_t * & parent,
-		const typename parent_t::child_t * child
-	) {
-		const auto & old_val = parent->*child;
-		if(!old_val) return;
-
-		auto new_val = call_accept(old_val);
-
-		if( __pass::differs(old_val, new_val) ) {
-			auto new_parent = mutate(parent);
-			new_parent->*child = new_val;
-			parent = new_parent;
 		}
 	}
@@ -106,13 +119,16 @@
 	template< typename pass_t >
 	template< typename node_t >
-	auto Pass< pass_t >::call_accept( const node_t * node ) {
+	auto Pass< pass_t >::call_accept( const node_t * node ) -> decltype( node->accept(*this) ) {
 		__pedantic_pass_assert( __visit_children() );
 		__pedantic_pass_assert( expr );
 
+		static_assert( !std::is_base_of<ast::Expr, node_t>::value, "ERROR");
+		static_assert( !std::is_base_of<ast::Stmt, node_t>::value, "ERROR");
+
 		return node->accept( *this );
 	}
 
 	template< typename pass_t >
-	ast::Expr * Pass< pass_t >::call_accept( const ast::Expr * expr ) {
+	const ast::Expr * Pass< pass_t >::call_accept( const ast::Expr * expr ) {
 		__pedantic_pass_assert( __visit_children() );
 		__pedantic_pass_assert( expr );
@@ -127,5 +143,5 @@
 
 	template< typename pass_t >
-	Stmt * Pass< pass_t >::call_accept( const Stmt * stmt ) {
+	const ast::Stmt * Pass< pass_t >::call_accept( const ast::Stmt * stmt ) {
 		__pedantic_pass_assert( __visit_children() );
 		__pedantic_pass_assert( stmt );
@@ -141,12 +157,12 @@
 
 		// 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< 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  );
 
 		// Now is the time to actually visit the node
-		ast::Statement * nstmt = stmt->accept( *this );
+		const ast::Stmt * nstmt = stmt->accept( *this );
 
 		// If the pass doesn't want to add anything then we are done
@@ -161,5 +177,5 @@
 
 		// Create a new Compound Statement to hold the new decls/stmts
-		ast::CompoundStmt * compound = new ast::CompoundStmt( parent->*child.location );
+		ast::CompoundStmt * compound = new ast::CompoundStmt( stmt->location );
 
 		// Take all the declarations that go before
@@ -168,5 +184,5 @@
 
 		// Insert the original declaration
-		compound->kids.push_back( nstmt );
+		compound->kids.emplace_back( nstmt );
 
 		// Insert all the declarations that go before
@@ -178,5 +194,5 @@
 
 	template< typename pass_t >
-	template< template <class> class container_t >
+	template< template <class...> class container_t >
 	container_t< ptr<Stmt> > Pass< pass_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {
 		__pedantic_pass_assert( __visit_children() );
@@ -196,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) > > __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  );
 
 		// update pass statitistics
@@ -211,5 +227,5 @@
 			try {
 				__pedantic_pass_assert( stmt );
-				const ast::Statment * new_stmt = stmt->accept( visitor );
+				const ast::Stmt * new_stmt = stmt->accept( *this );
 				assert( new_stmt );
 				if(new_stmt != stmt ) mutated = true;
@@ -240,9 +256,9 @@
 		if ( !errors.isEmpty() ) { throw errors; }
 
-		return mutated ? new_kids : {};
+		return mutated ? new_kids : container_t< ptr<Stmt> >();
 	}
 
 	template< typename pass_t >
-	template< template <class> class container_t, typename node_t >
+	template< template <class...> class container_t, typename node_t >
 	container_t< ast::ptr<node_t> > Pass< pass_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {
 		__pedantic_pass_assert( __visit_children() );
@@ -259,6 +275,6 @@
 			try {
 				__pedantic_pass_assert( node );
-				const node_t * new_node = strict_dynamic_cast< const node_t * >( node->accept( *this ) );
-				if(new_stmt != stmt ) mutated = true;
+				const node_t * new_stmt = strict_dynamic_cast< const node_t * >( node->accept( *this ) );
+				if(new_stmt != node ) mutated = true;
 
 				new_kids.emplace_back( new_stmt );
@@ -271,6 +287,31 @@
 		if ( ! errors.isEmpty() ) { throw errors; }
 
-		return mutated ? new_kids : {};
-	}
+		return mutated ? new_kids : container_t< ast::ptr<node_t> >();
+	}
+
+	template< typename pass_t >
+	template<typename node_t, typename parent_t, typename child_t>
+	void Pass< pass_t >::maybe_accept(
+		const node_t * & parent,
+		child_t parent_t::*child
+	) {
+		static_assert( std::is_base_of<parent_t, node_t>::value, "Error deductiing member object" );
+
+		if(__pass::skip(parent->*child)) return;
+		const auto & old_val = __pass::get(parent->*child, 0);
+
+		static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR");
+
+		auto new_val = call_accept( old_val );
+
+		static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR");
+
+		if( __pass::differs(old_val, new_val) ) {
+			auto new_parent = mutate(parent);
+			new_parent->*child = new_val;
+			parent = new_parent;
+		}
+	}
+
 }
 
@@ -284,5 +325,5 @@
 
 template< typename pass_t >
-inline void ast::acceptAll( std::list< ast::ptr<ast::Decl> > & decls, ast::Pass< pass_t > & visitor ) {
+inline void ast::accept_all( std::list< ast::ptr<ast::Decl> > & decls, ast::Pass< pass_t > & visitor ) {
 	// We are going to aggregate errors for all these statements
 	SemanticErrorException errors;
@@ -292,6 +333,6 @@
 
 	// get the stmts/decls that will need to be spliced in
-	auto decls_before = __pass::declsToAddBefore( pass, 0);
-	auto decls_after  = __pass::declsToAddAfter ( pass, 0);
+	auto decls_before = __pass::declsToAddBefore( visitor.pass, 0);
+	auto decls_after  = __pass::declsToAddAfter ( visitor.pass, 0);
 
 	// update pass statitistics
@@ -343,51 +384,118 @@
 // ObjectDecl
 template< typename pass_t >
-ast::DeclWithType * ast::Pass< pass_t >::visit( const ast::ObjectDecl * node ) {
+const ast::DeclWithType * ast::Pass< pass_t >::visit( const ast::ObjectDecl * node ) {
 	VISIT_START( node );
 
 	VISIT(
 		{
-			indexer_guard guard { *this };
-			maybe_accept( node, ObjectDecl::type );
-		}
-		maybe_accept( node, ObjectDecl::init          );
-		maybe_accept( node, ObjectDecl::bitfieldWidth );
-		maybe_accept( node, ObjectDecl::attributes    );
+			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    );
 	)
 
-	__pass::indexer::AddId( pass, 0, node );
+	__pass::indexer::addId( pass, 0, node );
 
 	VISIT_END( DeclWithType, node );
+}
+
+//--------------------------------------------------------------------------
+// SingleInit
+template< typename pass_t >
+const ast::Init * ast::Pass< pass_t >::visit( const ast::SingleInit * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		maybe_accept( node, &SingleInit::value );
+	)
+
+	VISIT_END( Init, node );
+}
+
+//--------------------------------------------------------------------------
+// ListInit
+template< typename pass_t >
+const ast::Init * ast::Pass< pass_t >::visit( const ast::ListInit * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		maybe_accept( node, &ListInit::designations );
+		maybe_accept( node, &ListInit::initializers );
+	)
+
+	VISIT_END( Init, node );
+}
+
+//--------------------------------------------------------------------------
+// ConstructorInit
+template< typename pass_t >
+const ast::Init * ast::Pass< pass_t >::visit( const ast::ConstructorInit * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		maybe_accept( node, &ConstructorInit::ctor );
+		maybe_accept( node, &ConstructorInit::dtor );
+		maybe_accept( node, &ConstructorInit::init );
+	)
+
+	VISIT_END( Init, node );
 }
 
 //--------------------------------------------------------------------------
 // Attribute
-template< typename pass_type >
-ast::Attribute * ast::Pass< pass_type >::visit( const ast::Attribute * node  )  {
-	VISIT_START(node);
+template< typename pass_t >
+const ast::Attribute * ast::Pass< pass_t >::visit( const ast::Attribute * node  )  {
+	VISIT_START( node );
 
 	VISIT(
-		maybe_accept( node, ast::Attribute::parameters );
+		maybe_accept( node, &Attribute::parameters );
 	)
 
-	VISIT_END(ast::Attribute *, node );
+	VISIT_END( Attribute *, node );
 }
 
 //--------------------------------------------------------------------------
 // TypeSubstitution
-template< typename pass_type >
-TypeSubstitution * PassVisitor< pass_type >::mutate( const TypeSubstitution * node ) {
-	MUTATE_START( node );
-
-	#error this is broken
-
-	for ( auto & p : node->typeEnv ) {
-		indexerScopedMutate( p.second, *this );
-	}
-	for ( auto & p : node->varEnv ) {
-		indexerScopedMutate( p.second, *this );
-	}
-
-	MUTATE_END( TypeSubstitution, node );
+template< typename pass_t >
+const ast::TypeSubstitution * ast::Pass< pass_t >::visit( const ast::TypeSubstitution * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		{
+			bool mutated = false;
+			std::unordered_map< std::string, ast::ptr< ast::Type > > new_map;
+			for ( const auto & p : node->typeEnv ) {
+				guard_indexer guard { *this };
+				auto new_node = p.second->accept( *this );
+				if (new_node != p.second) mutated = false;
+				new_map.insert({ p.first, new_node });
+			}
+			if (mutated) {
+				auto new_node = mutate( node );
+				new_node->typeEnv.swap( new_map );
+				node = new_node;
+			}
+		}
+
+		{
+			bool mutated = false;
+			std::unordered_map< std::string, ast::ptr< ast::Expr > > new_map;
+			for ( const auto & p : node->varEnv ) {
+				guard_indexer guard { *this };
+				auto new_node = p.second->accept( *this );
+				if (new_node != p.second) mutated = false;
+				new_map.insert({ p.first, new_node });
+			}
+			if (mutated) {
+				auto new_node = mutate( node );
+				new_node->varEnv.swap( new_map );
+				node = new_node;
+			}
+		}
+	)
+
+	VISIT_END( TypeSubstitution, node );
 }
 
Index: src/AST/Pass.proto.hpp
===================================================================
--- src/AST/Pass.proto.hpp	(revision 9e1d48503286c2f21bf3f599590920efc8b02293)
+++ src/AST/Pass.proto.hpp	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
@@ -162,5 +162,5 @@
 
 	// List of fields and their expected types
-	FIELD_PTR( env, const ast::TypeSubstitution )
+	FIELD_PTR( env, const ast::TypeSubstitution * )
 	FIELD_PTR( stmtsToAddBefore, std::list< ast::ptr< ast::Stmt > > )
 	FIELD_PTR( stmtsToAddAfter , std::list< ast::ptr< ast::Stmt > > )
@@ -235,52 +235,52 @@
 		static inline void func( pass_t &, long, type1, type2 ) {}
 
-		INDEXER_FUNC1( addId     , DeclWithType *  );
-		INDEXER_FUNC1( addType   , NamedTypeDecl * );
-		INDEXER_FUNC1( addStruct , StructDecl *    );
-		INDEXER_FUNC1( addEnum   , EnumDecl *      );
-		INDEXER_FUNC1( addUnion  , UnionDecl *     );
-		INDEXER_FUNC1( addTrait  , TraitDecl *     );
-		INDEXER_FUNC2( addWith   , std::list< Expression * > &, Node * );
+		INDEXER_FUNC1( addId     , const DeclWithType *  );
+		INDEXER_FUNC1( addType   , const NamedTypeDecl * );
+		INDEXER_FUNC1( addStruct , const StructDecl *    );
+		INDEXER_FUNC1( addEnum   , const EnumDecl *      );
+		INDEXER_FUNC1( addUnion  , const UnionDecl *     );
+		INDEXER_FUNC1( addTrait  , const TraitDecl *     );
+		INDEXER_FUNC2( addWith   , const std::list< Expression * > &, const Node * );
 
 		// A few extra functions have more complicated behaviour, they are hand written
-		// template<typename pass_t>
-		// static inline auto addStructFwd( pass_t & pass, int, ast::StructDecl * decl ) -> decltype( pass.indexer.addStruct( decl ), void() ) {
-		// 	ast::StructDecl * fwd = new ast::StructDecl( decl->location, decl->name );
-		// 	fwd->parameters = decl->parameters;
-		// 	pass.indexer.addStruct( fwd );
-		// }
-
-		// template<typename pass_t>
-		// static inline void addStructFwd( pass_t &, long, ast::StructDecl * ) {}
-
-		// template<typename pass_t>
-		// static inline auto addUnionFwd( pass_t & pass, int, ast::UnionDecl * decl ) -> decltype( pass.indexer.addUnion( decl ), void() ) {
-		// 	UnionDecl * fwd = new UnionDecl( decl->name );
-		// 	fwd->parameters = decl->parameters;
-		// 	pass.indexer.addUnion( fwd );
-		// }
-
-		// template<typename pass_t>
-		// static inline void addUnionFwd( pass_t &, long, ast::UnionDecl * ) {}
-
-		// template<typename pass_t>
-		// static inline auto addStruct( pass_t & pass, int, const std::string & str ) -> decltype( pass.indexer.addStruct( str ), void() ) {
-		// 	if ( ! pass.indexer.lookupStruct( str ) ) {
-		// 		pass.indexer.addStruct( str );
-		// 	}
-		// }
-
-		// template<typename pass_t>
-		// static inline void addStruct( pass_t &, long, const std::string & ) {}
-
-		// template<typename pass_t>
-		// static inline auto addUnion( pass_t & pass, int, const std::string & str ) -> decltype( pass.indexer.addUnion( str ), void() ) {
-		// 	if ( ! pass.indexer.lookupUnion( str ) ) {
-		// 		pass.indexer.addUnion( str );
-		// 	}
-		// }
-
-		// template<typename pass_t>
-		// static inline void addUnion( pass_t &, long, const std::string & ) {}
+		template<typename pass_t>
+		static inline auto addStructFwd( pass_t & pass, int, const ast::StructDecl * decl ) -> decltype( pass.indexer.addStruct( decl ), void() ) {
+			ast::StructDecl * fwd = new ast::StructDecl( decl->location, decl->name );
+			fwd->parameters = decl->parameters;
+			pass.indexer.addStruct( fwd );
+		}
+
+		template<typename pass_t>
+		static inline void addStructFwd( pass_t &, long, const ast::StructDecl * ) {}
+
+		template<typename pass_t>
+		static inline auto addUnionFwd( pass_t & pass, int, const ast::UnionDecl * decl ) -> decltype( pass.indexer.addUnion( decl ), void() ) {
+			UnionDecl * fwd = new UnionDecl( decl->location, decl->name );
+			fwd->parameters = decl->parameters;
+			pass.indexer.addUnion( fwd );
+		}
+
+		template<typename pass_t>
+		static inline void addUnionFwd( pass_t &, long, const ast::UnionDecl * ) {}
+
+		template<typename pass_t>
+		static inline auto addStruct( pass_t & pass, int, const std::string & str ) -> decltype( pass.indexer.addStruct( str ), void() ) {
+			if ( ! pass.indexer.lookupStruct( str ) ) {
+				pass.indexer.addStruct( str );
+			}
+		}
+
+		template<typename pass_t>
+		static inline void addStruct( pass_t &, long, const std::string & ) {}
+
+		template<typename pass_t>
+		static inline auto addUnion( pass_t & pass, int, const std::string & str ) -> decltype( pass.indexer.addUnion( str ), void() ) {
+			if ( ! pass.indexer.lookupUnion( str ) ) {
+				pass.indexer.addUnion( str );
+			}
+		}
+
+		template<typename pass_t>
+		static inline void addUnion( pass_t &, long, const std::string & ) {}
 
 		#undef INDEXER_FUNC1
Index: src/AST/Stmt.hpp
===================================================================
--- src/AST/Stmt.hpp	(revision 9e1d48503286c2f21bf3f599590920efc8b02293)
+++ src/AST/Stmt.hpp	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
@@ -40,5 +40,5 @@
 	Stmt(const Stmt& o) : ParseNode(o), labels(o.labels) {}
 
-	virtual Stmt* accept( Visitor& v ) override = 0;
+	virtual const Stmt* accept( Visitor& v ) const override = 0;
 private:
 	virtual Stmt* clone() const override = 0;
@@ -59,7 +59,7 @@
 	void push_front( Stmt* s ) { kids.emplace_front( s ); }
 
-	CompoundStmt* accept( Visitor& v ) override { return v.visit( this ); }
+	virtual const CompoundStmt* accept( Visitor& v ) const override { return v.visit( this ); }
 private:
-	CompoundStmt* clone() const override { return new CompoundStmt{ *this }; }
+	virtual CompoundStmt* clone() const override { return new CompoundStmt{ *this }; }
 };
 
@@ -70,7 +70,7 @@
 	: Stmt(loc, std::move(labels)) {}
 
-	NullStmt* accept( Visitor& v ) override { return v.visit( this ); }
+	virtual const NullStmt * accept( Visitor& v ) const override { return v.visit( this ); }
 private:
-	NullStmt* clone() const override { return new NullStmt{ *this }; }
+	virtual NullStmt * clone() const override { return new NullStmt{ *this }; }
 };
 
@@ -82,7 +82,7 @@
 	ExprStmt( const CodeLocation& loc, Expr* e ) : Stmt(loc), expr(e) {}
 
-	Stmt* accept( Visitor& v ) override { return v.visit( this ); }
+	virtual const Stmt * accept( Visitor& v ) const override { return v.visit( this ); }
 private:
-	ExprStmt* clone() const override { return new ExprStmt{ *this }; }
+	virtual ExprStmt * clone() const override { return new ExprStmt{ *this }; }
 };
 
@@ -100,40 +100,40 @@
 inline void increment( const class ExprStmt * node, Node::ref_type ref ) { node->increment( ref ); }
 inline void decrement( const class ExprStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class AsmStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class AsmStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class DirectiveStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class DirectiveStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class IfStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class IfStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class WhileStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class WhileStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class ForStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ForStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class SwitchStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class SwitchStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class CaseStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class CaseStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class BranchStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class BranchStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class ReturnStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ReturnStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class ThrowStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ThrowStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class TryStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class TryStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class CatchStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class CatchStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class FinallyStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class FinallyStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class WaitForStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class WaitForStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class WithStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class WithStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class DeclStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class DeclStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+// inline void increment( const class AsmStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+// inline void decrement( const class AsmStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+// inline void increment( const class DirectiveStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+// inline void decrement( const class DirectiveStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+// inline void increment( const class IfStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+// inline void decrement( const class IfStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+// inline void increment( const class WhileStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+// inline void decrement( const class WhileStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+// inline void increment( const class ForStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+// inline void decrement( const class ForStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+// inline void increment( const class SwitchStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+// inline void decrement( const class SwitchStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+// inline void increment( const class CaseStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+// inline void decrement( const class CaseStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+// inline void increment( const class BranchStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+// inline void decrement( const class BranchStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+// inline void increment( const class ReturnStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+// inline void decrement( const class ReturnStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+// inline void increment( const class ThrowStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+// inline void decrement( const class ThrowStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+// inline void increment( const class TryStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+// inline void decrement( const class TryStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+// inline void increment( const class CatchStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+// inline void decrement( const class CatchStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+// inline void increment( const class FinallyStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+// inline void decrement( const class FinallyStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+// inline void increment( const class WaitForStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+// inline void decrement( const class WaitForStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+// inline void increment( const class WithStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+// inline void decrement( const class WithStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+// inline void increment( const class DeclStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+// inline void decrement( const class DeclStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
 inline void increment( const class NullStmt * node, Node::ref_type ref ) { node->increment( ref ); }
 inline void decrement( const class NullStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class ImplicitCtorDtorStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ImplicitCtorDtorStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+// inline void increment( const class ImplicitCtorDtorStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+// inline void decrement( const class ImplicitCtorDtorStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
 
 }
Index: src/AST/Type.cpp
===================================================================
--- src/AST/Type.cpp	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
+++ src/AST/Type.cpp	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
@@ -0,0 +1,181 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// Type.cpp --
+//
+// Author           : Aaron B. Moss
+// Created On       : Mon May 13 15:00:00 2019
+// Last Modified By : Aaron B. Moss
+// Last Modified On : Mon May 13 15:00:00 2019
+// Update Count     : 1
+//
+
+#include "Type.hpp"
+
+#include <cassert>
+#include <utility>               // for move
+#include <vector>
+
+#include "Decl.hpp"
+#include "Init.hpp"
+#include "InitTweak/InitTweak.h" // for getPointerBase
+#include "Tuples/Tuples.h"       // for isTtype
+
+namespace ast {
+
+const Type * Type::getComponent( unsigned i ) {
+	assertf( size() == 1 && i == 0, "Type::getComponent was called with size %d and index %d\n", size(), i );
+	return this;
+}
+
+const Type * Type::stripDeclarator() {
+	const Type * t;
+	const Type * a;
+	for ( t = this; (a = InitTweak::getPointerBase( t )); t = a );
+	return t;
+}
+
+const Type * Type::stripReferences() {
+	const Type * t;
+	const ReferenceType * r;
+	for ( t = this; (r = dynamic_cast<const ReferenceType *>() ); t = r->base );
+	return t;
+}
+
+// --- BasicType
+
+const char *BasicType::typeNames[] = {
+	"_Bool",
+	"char",
+	"signed char",
+	"unsigned char",
+	"signed short int",
+	"unsigned short int",
+	"signed int",
+	"unsigned int",
+	"signed long int",
+	"unsigned long int",
+	"signed long long int",
+	"unsigned long long int",
+	"__int128",
+	"unsigned __int128",
+	"_Float16",
+	"_Float16 _Complex",
+	"_Float32",
+	"_Float32 _Complex",
+	"float",
+	"float _Complex",
+	"_Float32x",
+	"_Float32x _Complex",
+	"_Float64",
+	"_Float64 _Complex",
+	"double",
+	"double _Complex",
+	"_Float64x",
+	"_Float64x _Complex",
+	"__float80",
+	"_Float128",
+	"_Float128 _Complex",
+	"__float128",
+	"long double",
+	"long double _Complex",
+	"_Float128x",
+	"_Float128x _Complex",
+};
+static_assert(
+	sizeof(BasicType::typeNames)/sizeof(BasicType::typeNames[0]) == BasicType::NUMBER_OF_BASIC_TYPES,
+	"Each basic type name should have a corresponding kind enum value"
+);
+
+// --- FunctionType
+
+namespace {
+	bool containsTtype( const std::vector<ptr<DeclWithType>> & l ) {
+		if ( ! l.empty() ) {
+			return Tuples::isTtype( l.back()->get_type() );
+		}
+		return false;
+	}
+}
+
+bool FunctionType::isTtype() const {
+	return containsTtype( returnVals ) || containsTtype( parameters );
+}
+
+// --- ReferenceToType
+std::vector<readonly<Decl>> ReferenceToType::lookup( const std::string& name ) const {
+	assertf( aggr(), "Must have aggregate to perform lookup" );
+	
+	std::vector<readonly<Decl>> found;
+	for ( const Decl * decl : aggr()->members ) {
+		if ( decl->name == name ) { found.emplace_back( decl ); }
+	}
+	return found;
+}
+
+// --- StructInstType
+
+StructInstType::StructInstType( const StructDecl * b, CV::Qualifiers q = {}, 
+	std::vector<ptr<Attribute>>&& as = {} )
+: ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
+
+bool StructInstType::isComplete() const { return base ? base->body : false; }
+
+// --- UnionInstType
+
+UnionInstType::UnionInstType( const UnionDecl * b, CV::Qualifiers q = {}, 
+	std::vector<ptr<Attribute>>&& as = {} )
+: ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
+
+bool UnionInstType::isComplete() const { return base ? base->body : false; }
+
+// --- EnumInstType
+
+EnumInstType::EnumInstType( const EnumDecl * b, CV::Qualifiers q = {}, 
+	std::vector<ptr<Attribute>>&& as = {} )
+: ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
+
+bool EnumInstType::isComplete() const { return base ? base->body : false; }
+
+// --- TypeInstType
+
+void TypeInstType::set_base( const TypeDecl * b ) {
+	base = b;
+	kind = b->kind;
+}
+
+bool TypeInstType::isComplete() const { return base->sized; }
+
+// --- TupleType
+
+TupleType::TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q = {} )
+: Type( q ), types( std::move(ts) ), members() {
+	// This constructor is awkward. `TupleType` needs to contain objects so that members can be 
+	// named, but members without initializer nodes end up getting constructors, which breaks 
+	// things. This happens because the object decls have to be visited so that their types are 
+	// kept in sync with the types listed here. Ultimately, the types listed here should perhaps 
+	// be eliminated and replaced with a list-view over members. The temporary solution is to 
+	// make a `ListInit` with `maybeConstructed = false`, so when the object is visited it is not 
+	// constructed. Potential better solutions include:
+	//   a) Separate `TupleType` from its declarations, into `TupleDecl` and `Tuple{Inst?}Type`, 
+	//      similar to the aggregate types.
+	//   b) Separate initializer nodes better, e.g. add a `MaybeConstructed` node that is replaced 
+	//      by `genInit`, rather than the current boolean flag.
+	members.reserve( types.size() );
+	for ( const Type * ty : types ) {
+		members.emplace_back( new ObjectDecl{
+			CodeLocation{}, "", ty, new ListInit( CodeLocation{}, {}, {}, MaybeConstruct ), 
+			Storage::Classes{}, Linkage::Cforall } );
+	}
+}
+
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/AST/Type.hpp
===================================================================
--- src/AST/Type.hpp	(revision 9e1d48503286c2f21bf3f599590920efc8b02293)
+++ src/AST/Type.hpp	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
@@ -67,5 +67,5 @@
 	virtual bool isComplete() const { return true; }
 
-	virtual Type * accept( Visitor & v ) override = 0;
+	virtual const Type * accept( Visitor & v ) const override = 0;
 private:
 	virtual Type * clone() const override = 0;
@@ -81,5 +81,5 @@
 	bool isComplete() const override { return false; }
 
-	Type * accept( Visitor & v ) override { return v.visit( this ); }
+	const Type * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
 	VoidType * clone() const override { return new VoidType{ *this }; }
@@ -143,5 +143,5 @@
 	bool isInteger() const { return kind <= MAX_INTEGER_TYPE; }
 
-	Type * accept( Visitor & v ) override { return v.visit( this ); }
+	const Type * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
 	BasicType * clone() const override { return new BasicType{ *this }; }
@@ -173,5 +173,5 @@
 	bool isComplete() const override { return ! isVarLen; }
 
-	Type * accept( Visitor & v ) override { return v.visit( this ); }
+	const Type * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
 	PointerType * clone() const override { return new PointerType{ *this }; }
@@ -194,5 +194,5 @@
 	bool isComplete() const override { return dimension || isVarLen; }
 
-	Type * accept( Visitor & v ) override { return v.visit( this ); }
+	const Type * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
 	ArrayType * clone() const override { return new ArrayType{ *this }; }
@@ -213,5 +213,5 @@
 	unsigned size() const override { return base->size(); }
 
-	Type * accept( Visitor & v ) override { return v.visit( this ); }
+	const Type * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
 	ReferenceType * clone() const override { return new ReferenceType{ *this }; }
@@ -227,5 +227,5 @@
 	: Type(q), parent(p), child(c) {}
 
-	Type * accept( Visitor & v ) override { return v.visit( this ); }
+	const Type * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
 	QualifiedType * clone() const override { return new QualifiedType{ *this }; }
@@ -271,5 +271,5 @@
 	bool isUnprototyped() const { return isVarArgs && parameters.size() == 0; }
 
-	Type * accept( Visitor & v ) override { return v.visit( this ); }
+	const Type * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
 	FunctionType * clone() const override { return new FunctionType{ *this }; }
@@ -316,5 +316,5 @@
 	const StructDecl * aggr() const override { return base; }
 
-	Type * accept( Visitor & v ) override { return v.visit( this ); }
+	const Type * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
 	StructInstType * clone() const override { return new StructInstType{ *this }; }
@@ -338,5 +338,5 @@
 	const UnionDecl * aggr() const override { return base; }
 
-	Type * accept( Visitor & v ) override { return v.visit( this ); }
+	const Type * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
 	UnionInstType * clone() const override { return new UnionInstType{ *this }; }
@@ -360,5 +360,5 @@
 	const EnumDecl * aggr() const override { return base; }
 
-	Type * accept( Visitor & v ) override { return v.visit( this ); }
+	const Type * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
 	EnumInstType * clone() const override { return new EnumInstType{ *this }; }
@@ -383,5 +383,5 @@
 	const TraitDecl * aggr() const override { return base; }
 
-	Type * accept( Visitor & v ) override { return v.visit( this ); }
+	const Type * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
 	TraitInstType * clone() const override { return new TraitInstType{ *this }; }
@@ -411,5 +411,5 @@
 	const AggregateDecl * aggr() const override { assert(false); }
 
-	Type * accept( Visitor & v ) override { return v.visit( this ); }
+	const Type * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
 	TypeInstType * clone() const override { return new TypeInstType{ *this }; }
@@ -439,5 +439,5 @@
 	}
 
-	Type * accept( Visitor & v ) override { return v.visit( this ); }
+	const Type * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
 	TupleType * clone() const override { return new TupleType{ *this }; }
@@ -453,5 +453,5 @@
 	: Type(q), expr(e), kind(k) {}
 
-	Type * accept( Visitor & v ) override { return v.visit( this ); }
+	const Type * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
 	TypeofType * clone() const override { return new TypeofType{ *this }; }
@@ -463,5 +463,5 @@
 	VarArgsType( CV::Qualifiers q = {} ) : Type( q ) {}
 	
-	Type * accept( Visitor & v ) override { return v.visit( this ); }
+	const Type * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
 	VarArgsType * clone() const override { return new VarArgsType{ *this }; }
@@ -473,5 +473,5 @@
 	ZeroType( CV::Qualifiers q = {} ) : Type( q ) {}
 	
-	Type * accept( Visitor & v ) override { return v.visit( this ); }
+	const Type * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
 	ZeroType * clone() const override { return new ZeroType{ *this }; }	
@@ -483,5 +483,5 @@
 	OneType( CV::Qualifiers q = {} ) : Type( q ) {}
 
-	Type * accept( Visitor & v ) override { return v.visit( this ); }
+	const Type * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
 	OneType * clone() const override { return new OneType{ *this }; }
@@ -493,5 +493,5 @@
 	GlobalScopeType( CV::Qualifiers q = {} ) : Type( q ) {}
 
-	Type * accept( Visitor & v ) override { return v.visit( this ); }
+	const Type * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
 	GlobalScopeType * clone() const override { return new GlobalScopeType{ *this }; }
Index: src/AST/Visitor.hpp
===================================================================
--- src/AST/Visitor.hpp	(revision 9e1d48503286c2f21bf3f599590920efc8b02293)
+++ src/AST/Visitor.hpp	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
@@ -22,97 +22,97 @@
 class Visitor {
 public:
-    virtual DeclWithType *     visit( const ObjectDecl           * ) = 0;
-    virtual DeclWithType *     visit( const FunctionDecl         * ) = 0;
-    virtual Decl *             visit( const StructDecl           * ) = 0;
-    virtual Decl *             visit( const UnionDecl            * ) = 0;
-    virtual Decl *             visit( const EnumDecl             * ) = 0;
-    virtual Decl *             visit( const TraitDecl            * ) = 0;
-    virtual Decl *             visit( const TypeDecl             * ) = 0;
-    virtual Decl *             visit( const TypedefDecl          * ) = 0;
-    virtual AsmDecl *          visit( const AsmDecl              * ) = 0;
-    virtual StaticAssertDecl * visit( const StaticAssertDecl     * ) = 0;
-    virtual CompoundStmt *     visit( const CompoundStmt         * ) = 0;
-    virtual Stmt *             visit( const ExprStmt             * ) = 0;
-    virtual Stmt *             visit( const AsmStmt              * ) = 0;
-    virtual Stmt *             visit( const DirectiveStmt        * ) = 0;
-    virtual Stmt *             visit( const IfStmt               * ) = 0;
-    virtual Stmt *             visit( const WhileStmt            * ) = 0;
-    virtual Stmt *             visit( const ForStmt              * ) = 0;
-    virtual Stmt *             visit( const SwitchStmt           * ) = 0;
-    virtual Stmt *             visit( const CaseStmt             * ) = 0;
-    virtual Stmt *             visit( const BranchStmt           * ) = 0;
-    virtual Stmt *             visit( const ReturnStmt           * ) = 0;
-    virtual Stmt *             visit( const ThrowStmt            * ) = 0;
-    virtual Stmt *             visit( const TryStmt              * ) = 0;
-    virtual Stmt *             visit( const CatchStmt            * ) = 0;
-    virtual Stmt *             visit( const FinallyStmt          * ) = 0;
-    virtual Stmt *             visit( const WaitForStmt          * ) = 0;
-    virtual Stmt *             visit( const WithStmt             * ) = 0;
-    virtual NullStmt *         visit( const NullStmt             * ) = 0;
-    virtual Stmt *             visit( const DeclStmt             * ) = 0;
-    virtual Stmt *             visit( const ImplicitCtorDtorStmt * ) = 0;
-    virtual Expr *             visit( const ApplicationExpr      * ) = 0;
-    virtual Expr *             visit( const UntypedExpr          * ) = 0;
-    virtual Expr *             visit( const NameExpr             * ) = 0;
-    virtual Expr *             visit( const AddressExpr          * ) = 0;
-    virtual Expr *             visit( const LabelAddressExpr     * ) = 0;
-    virtual Expr *             visit( const CastExpr             * ) = 0;
-    virtual Expr *             visit( const KeywordCastExpr      * ) = 0;
-    virtual Expr *             visit( const VirtualCastExpr      * ) = 0;
-    virtual Expr *             visit( const UntypedMemberExpr    * ) = 0;
-    virtual Expr *             visit( const MemberExpr           * ) = 0;
-    virtual Expr *             visit( const VariableExpr         * ) = 0;
-    virtual Expr *             visit( const ConstantExpr         * ) = 0;
-    virtual Expr *             visit( const SizeofExpr           * ) = 0;
-    virtual Expr *             visit( const AlignofExpr          * ) = 0;
-    virtual Expr *             visit( const UntypedOffsetofExpr  * ) = 0;
-    virtual Expr *             visit( const OffsetofExpr         * ) = 0;
-    virtual Expr *             visit( const OffsetPackExpr       * ) = 0;
-    virtual Expr *             visit( const AttrExpr             * ) = 0;
-    virtual Expr *             visit( const LogicalExpr          * ) = 0;
-    virtual Expr *             visit( const ConditionalExpr      * ) = 0;
-    virtual Expr *             visit( const CommaExpr            * ) = 0;
-    virtual Expr *             visit( const TypeExpr             * ) = 0;
-    virtual Expr *             visit( const AsmExpr              * ) = 0;
-    virtual Expr *             visit( const ImplicitCopyCtorExpr * ) = 0;
-    virtual Expr *             visit( const ConstructorExpr      * ) = 0;
-    virtual Expr *             visit( const CompoundLiteralExpr  * ) = 0;
-    virtual Expr *             visit( const RangeExpr            * ) = 0;
-    virtual Expr *             visit( const UntypedTupleExpr     * ) = 0;
-    virtual Expr *             visit( const TupleExpr            * ) = 0;
-    virtual Expr *             visit( const TupleIndexExpr       * ) = 0;
-    virtual Expr *             visit( const TupleAssignExpr      * ) = 0;
-    virtual Expr *             visit( const StmtExpr             * ) = 0;
-    virtual Expr *             visit( const UniqueExpr           * ) = 0;
-    virtual Expr *             visit( const UntypedInitExpr      * ) = 0;
-    virtual Expr *             visit( const InitExpr             * ) = 0;
-    virtual Expr *             visit( const DeletedExpr          * ) = 0;
-    virtual Expr *             visit( const DefaultArgExpr       * ) = 0;
-    virtual Expr *             visit( const GenericExpr          * ) = 0;
-    virtual Type *             visit( const VoidType             * ) = 0;
-    virtual Type *             visit( const BasicType            * ) = 0;
-    virtual Type *             visit( const PointerType          * ) = 0;
-    virtual Type *             visit( const ArrayType            * ) = 0;
-    virtual Type *             visit( const ReferenceType        * ) = 0;
-    virtual Type *             visit( const QualifiedType        * ) = 0;
-    virtual Type *             visit( const FunctionType         * ) = 0;
-    virtual Type *             visit( const StructInstType       * ) = 0;
-    virtual Type *             visit( const UnionInstType        * ) = 0;
-    virtual Type *             visit( const EnumInstType         * ) = 0;
-    virtual Type *             visit( const TraitInstType        * ) = 0;
-    virtual Type *             visit( const TypeInstType         * ) = 0;
-    virtual Type *             visit( const TupleType            * ) = 0;
-    virtual Type *             visit( const TypeofType           * ) = 0;
-    virtual Type *             visit( const VarArgsType          * ) = 0;
-    virtual Type *             visit( const ZeroType             * ) = 0;
-    virtual Type *             visit( const OneType              * ) = 0;
-    virtual Type *             visit( const GlobalScopeType      * ) = 0;
-    virtual Designation *      visit( const Designation          * ) = 0;
-    virtual Init *             visit( const SingleInit           * ) = 0;
-    virtual Init *             visit( const ListInit             * ) = 0;
-    virtual Init *             visit( const ConstructorInit      * ) = 0;
-    virtual Constant *         visit( const Constant             * ) = 0;
-    virtual Attribute *        visit( const Attribute            * ) = 0;
-    virtual TypeSubstitution * visit( const TypeSubstitution     * ) = 0;
+    virtual const ast::DeclWithType *     visit( const ast::ObjectDecl           * ) = 0;
+    virtual const ast::DeclWithType *     visit( const ast::FunctionDecl         * ) = 0;
+    virtual const ast::Decl *             visit( const ast::StructDecl           * ) = 0;
+    virtual const ast::Decl *             visit( const ast::UnionDecl            * ) = 0;
+    virtual const ast::Decl *             visit( const ast::EnumDecl             * ) = 0;
+    virtual const ast::Decl *             visit( const ast::TraitDecl            * ) = 0;
+    virtual const ast::Decl *             visit( const ast::TypeDecl             * ) = 0;
+    virtual const ast::Decl *             visit( const ast::TypedefDecl          * ) = 0;
+    virtual const ast::AsmDecl *          visit( const ast::AsmDecl              * ) = 0;
+    virtual const ast::StaticAssertDecl * visit( const ast::StaticAssertDecl     * ) = 0;
+    virtual const ast::CompoundStmt *     visit( const ast::CompoundStmt         * ) = 0;
+    virtual const ast::Stmt *             visit( const ast::ExprStmt             * ) = 0;
+    virtual const ast::Stmt *             visit( const ast::AsmStmt              * ) = 0;
+    virtual const ast::Stmt *             visit( const ast::DirectiveStmt        * ) = 0;
+    virtual const ast::Stmt *             visit( const ast::IfStmt               * ) = 0;
+    virtual const ast::Stmt *             visit( const ast::WhileStmt            * ) = 0;
+    virtual const ast::Stmt *             visit( const ast::ForStmt              * ) = 0;
+    virtual const ast::Stmt *             visit( const ast::SwitchStmt           * ) = 0;
+    virtual const ast::Stmt *             visit( const ast::CaseStmt             * ) = 0;
+    virtual const ast::Stmt *             visit( const ast::BranchStmt           * ) = 0;
+    virtual const ast::Stmt *             visit( const ast::ReturnStmt           * ) = 0;
+    virtual const ast::Stmt *             visit( const ast::ThrowStmt            * ) = 0;
+    virtual const ast::Stmt *             visit( const ast::TryStmt              * ) = 0;
+    virtual const ast::Stmt *             visit( const ast::CatchStmt            * ) = 0;
+    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::NullStmt *         visit( const ast::NullStmt             * ) = 0;
+    virtual const ast::Stmt *             visit( const ast::DeclStmt             * ) = 0;
+    virtual const ast::Stmt *             visit( const ast::ImplicitCtorDtorStmt * ) = 0;
+    virtual const ast::Expr *             visit( const ast::ApplicationExpr      * ) = 0;
+    virtual const ast::Expr *             visit( const ast::UntypedExpr          * ) = 0;
+    virtual const ast::Expr *             visit( const ast::NameExpr             * ) = 0;
+    virtual const ast::Expr *             visit( const ast::AddressExpr          * ) = 0;
+    virtual const ast::Expr *             visit( const ast::LabelAddressExpr     * ) = 0;
+    virtual const ast::Expr *             visit( const ast::CastExpr             * ) = 0;
+    virtual const ast::Expr *             visit( const ast::KeywordCastExpr      * ) = 0;
+    virtual const ast::Expr *             visit( const ast::VirtualCastExpr      * ) = 0;
+    virtual const ast::Expr *             visit( const ast::UntypedMemberExpr    * ) = 0;
+    virtual const ast::Expr *             visit( const ast::MemberExpr           * ) = 0;
+    virtual const ast::Expr *             visit( const ast::VariableExpr         * ) = 0;
+    virtual const ast::Expr *             visit( const ast::ConstantExpr         * ) = 0;
+    virtual const ast::Expr *             visit( const ast::SizeofExpr           * ) = 0;
+    virtual const ast::Expr *             visit( const ast::AlignofExpr          * ) = 0;
+    virtual const ast::Expr *             visit( const ast::UntypedOffsetofExpr  * ) = 0;
+    virtual const ast::Expr *             visit( const ast::OffsetofExpr         * ) = 0;
+    virtual const ast::Expr *             visit( const ast::OffsetPackExpr       * ) = 0;
+    virtual const ast::Expr *             visit( const ast::AttrExpr             * ) = 0;
+    virtual const ast::Expr *             visit( const ast::LogicalExpr          * ) = 0;
+    virtual const ast::Expr *             visit( const ast::ConditionalExpr      * ) = 0;
+    virtual const ast::Expr *             visit( const ast::CommaExpr            * ) = 0;
+    virtual const ast::Expr *             visit( const ast::TypeExpr             * ) = 0;
+    virtual const ast::Expr *             visit( const ast::AsmExpr              * ) = 0;
+    virtual const ast::Expr *             visit( const ast::ImplicitCopyCtorExpr * ) = 0;
+    virtual const ast::Expr *             visit( const ast::ConstructorExpr      * ) = 0;
+    virtual const ast::Expr *             visit( const ast::CompoundLiteralExpr  * ) = 0;
+    virtual const ast::Expr *             visit( const ast::RangeExpr            * ) = 0;
+    virtual const ast::Expr *             visit( const ast::UntypedTupleExpr     * ) = 0;
+    virtual const ast::Expr *             visit( const ast::TupleExpr            * ) = 0;
+    virtual const ast::Expr *             visit( const ast::TupleIndexExpr       * ) = 0;
+    virtual const ast::Expr *             visit( const ast::TupleAssignExpr      * ) = 0;
+    virtual const ast::Expr *             visit( const ast::StmtExpr             * ) = 0;
+    virtual const ast::Expr *             visit( const ast::UniqueExpr           * ) = 0;
+    virtual const ast::Expr *             visit( const ast::UntypedInitExpr      * ) = 0;
+    virtual const ast::Expr *             visit( const ast::InitExpr             * ) = 0;
+    virtual const ast::Expr *             visit( const ast::DeletedExpr          * ) = 0;
+    virtual const ast::Expr *             visit( const ast::DefaultArgExpr       * ) = 0;
+    virtual const ast::Expr *             visit( const ast::GenericExpr          * ) = 0;
+    virtual const ast::Type *             visit( const ast::VoidType             * ) = 0;
+    virtual const ast::Type *             visit( const ast::BasicType            * ) = 0;
+    virtual const ast::Type *             visit( const ast::PointerType          * ) = 0;
+    virtual const ast::Type *             visit( const ast::ArrayType            * ) = 0;
+    virtual const ast::Type *             visit( const ast::ReferenceType        * ) = 0;
+    virtual const ast::Type *             visit( const ast::QualifiedType        * ) = 0;
+    virtual const ast::Type *             visit( const ast::FunctionType         * ) = 0;
+    virtual const ast::Type *             visit( const ast::StructInstType       * ) = 0;
+    virtual const ast::Type *             visit( const ast::UnionInstType        * ) = 0;
+    virtual const ast::Type *             visit( const ast::EnumInstType         * ) = 0;
+    virtual const ast::Type *             visit( const ast::TraitInstType        * ) = 0;
+    virtual const ast::Type *             visit( const ast::TypeInstType         * ) = 0;
+    virtual const ast::Type *             visit( const ast::TupleType            * ) = 0;
+    virtual const ast::Type *             visit( const ast::TypeofType           * ) = 0;
+    virtual const ast::Type *             visit( const ast::VarArgsType          * ) = 0;
+    virtual const ast::Type *             visit( const ast::ZeroType             * ) = 0;
+    virtual const ast::Type *             visit( const ast::OneType              * ) = 0;
+    virtual const ast::Type *             visit( const ast::GlobalScopeType      * ) = 0;
+    virtual const ast::Designation *      visit( const ast::Designation          * ) = 0;
+    virtual const ast::Init *             visit( const ast::SingleInit           * ) = 0;
+    virtual const ast::Init *             visit( const ast::ListInit             * ) = 0;
+    virtual const ast::Init *             visit( const ast::ConstructorInit      * ) = 0;
+    virtual const ast::Constant *         visit( const ast::Constant             * ) = 0;
+    virtual const ast::Attribute *        visit( const ast::Attribute            * ) = 0;
+    virtual const ast::TypeSubstitution * visit( const ast::TypeSubstitution     * ) = 0;
 };
 
Index: src/AST/porting.md
===================================================================
--- src/AST/porting.md	(revision 9e1d48503286c2f21bf3f599590920efc8b02293)
+++ src/AST/porting.md	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
@@ -10,5 +10,5 @@
 ## Visitors ##
 * `Visitor` and `Mutator` are combined into a single `ast::Visitor` class
-  * Base nodes now override `Node* accept( Visitor& v ) = 0` with, e.g. `Stmt* accept( Visitor& v ) override = 0`
+  * Base nodes now override `const Node * accept( Visitor & v ) const = 0` with, e.g. `const Stmt * accept( Visitor & v ) const override = 0`
 * `PassVisitor` is replaced with `ast::Pass`
 
@@ -26,5 +26,9 @@
 `clone` is private to `Node` now
 * still needs to be overriden to return appropriate type
-  * e.g. `private: virtual Stmt* clone() const override = 0;`
+  * e.g. `private: virtual Stmt * clone() const override = 0;`
+  * because friendship is not inherited, all implementations of clone need
+      /// Must be copied in ALL derived classes
+      template<typename node_t>
+      friend auto mutate(const node_t * node);
 
 All leaves of the `Node` inheritance tree are now declared `final`
@@ -170,6 +174,6 @@
 
 `AttrType`
-* did not port due to (likely) disuse
-  * best guess at use (from printing code) is deprecated handling for attributes
+* did not port due to deprecation of feature
+  * feature is `type@thing` e.g. `int@MAX`
 
 [1] https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gcc/Type-Attributes.html#Type-Attributes
Index: src/Common/PassVisitor.h
===================================================================
--- src/Common/PassVisitor.h	(revision 9e1d48503286c2f21bf3f599590920efc8b02293)
+++ src/Common/PassVisitor.h	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
@@ -155,6 +155,4 @@
 	virtual void visit( ConstructorInit * ctorInit ) override final;
 
-	virtual void visit( Subrange * subrange ) override final;
-
 	virtual void visit( Constant * constant ) override final;
 
@@ -257,6 +255,4 @@
 	virtual Initializer * mutate( ConstructorInit * ctorInit ) override final;
 
-	virtual Subrange * mutate( Subrange * subrange ) override final;
-
 	virtual Constant * mutate( Constant * constant ) override final;
 
Index: src/Common/PassVisitor.impl.h
===================================================================
--- src/Common/PassVisitor.impl.h	(revision 9e1d48503286c2f21bf3f599590920efc8b02293)
+++ src/Common/PassVisitor.impl.h	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
@@ -2712,20 +2712,4 @@
 
 //--------------------------------------------------------------------------
-// Subrange
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( Subrange * node ) {
-	VISIT_START( node );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Subrange * PassVisitor< pass_type >::mutate( Subrange * node  )  {
-	MUTATE_START( node );
-
-	MUTATE_END( Subrange, node );
-}
-
-//--------------------------------------------------------------------------
 // Attribute
 template< typename pass_type >
Index: src/SynTree/Declaration.h
===================================================================
--- src/SynTree/Declaration.h	(revision 9e1d48503286c2f21bf3f599590920efc8b02293)
+++ src/SynTree/Declaration.h	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
@@ -245,5 +245,4 @@
 	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
 
-  private:
 	Kind kind;
 };
@@ -306,6 +305,6 @@
 	virtual void accept( Visitor &v ) override { v.visit( this ); }
 	virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
-  private:
 	DeclarationNode::Aggregate kind;
+  private:
 	virtual std::string typeString() const override;
 };
Index: src/SynTree/Label.h
===================================================================
--- src/SynTree/Label.h	(revision 9e1d48503286c2f21bf3f599590920efc8b02293)
+++ src/SynTree/Label.h	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
@@ -35,5 +35,5 @@
 	operator std::string() const { return name; }
 	bool empty() { return name.empty(); }
-  private:
+
 	std::string name;
 	Statement * labelled;
Index: src/SynTree/Mutator.h
===================================================================
--- src/SynTree/Mutator.h	(revision 9e1d48503286c2f21bf3f599590920efc8b02293)
+++ src/SynTree/Mutator.h	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
@@ -121,6 +121,4 @@
 	virtual Initializer * mutate( ConstructorInit * ctorInit ) = 0 ;
 
-	virtual Subrange * mutate( Subrange * subrange ) = 0;
-
 	virtual Constant * mutate( Constant * constant ) = 0;
 
Index: src/SynTree/SynTree.h
===================================================================
--- src/SynTree/SynTree.h	(revision 9e1d48503286c2f21bf3f599590920efc8b02293)
+++ src/SynTree/SynTree.h	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
@@ -132,6 +132,4 @@
 class ConstructorInit;
 
-class Subrange;
-
 //template <class T>	// emulate a union with templates?
 class Constant;
Index: src/SynTree/Visitor.h
===================================================================
--- src/SynTree/Visitor.h	(revision 9e1d48503286c2f21bf3f599590920efc8b02293)
+++ src/SynTree/Visitor.h	(revision 69bafd262c8310d9ad78a0b8e5d5ebd7d9b9152c)
@@ -123,6 +123,4 @@
 	virtual void visit( ConstructorInit * ctorInit ) = 0;
 
-	virtual void visit( Subrange * subrange ) = 0;
-
 	virtual void visit( Constant * constant ) = 0;
 
