Index: src/AST/SymbolTable.cpp
===================================================================
--- src/AST/SymbolTable.cpp	(revision 70056edafe6b115773f5da41e81a7b2adf5c08f5)
+++ src/AST/SymbolTable.cpp	(revision e02e13fc53b4a6d659a7753b2c843a4b7e203c0d)
@@ -70,5 +70,5 @@
 	if ( baseExpr ) {
 		if (baseExpr->env) {
-			Expr * base = shallowCopy(baseExpr);
+			Expr * base = deepCopy(baseExpr);
 			const TypeSubstitution * subs = baseExpr->env;
 			base->env = nullptr;
Index: src/Parser/DeclarationNode.cc
===================================================================
--- src/Parser/DeclarationNode.cc	(revision 70056edafe6b115773f5da41e81a7b2adf5c08f5)
+++ src/Parser/DeclarationNode.cc	(revision e02e13fc53b4a6d659a7753b2c843a4b7e203c0d)
@@ -10,6 +10,6 @@
 // Created On       : Sat May 16 12:34:05 2015
 // Last Modified By : Andrew Beach
-// Last Modified On : Tue Mar 14 11:56:00 2023
-// Update Count     : 1406
+// Last Modified On : Tue Apr  4 10:28:00 2023
+// Update Count     : 1392
 //
 
@@ -21,14 +21,18 @@
 #include <string>                  // for string, operator+, allocator, char...
 
+#include "AST/Attribute.hpp"       // for Attribute
+#include "AST/Copy.hpp"            // for shallowCopy
+#include "AST/Decl.hpp"            // for Decl
+#include "AST/Expr.hpp"            // for Expr
+#include "AST/Print.hpp"           // for print
+#include "AST/Stmt.hpp"            // for AsmStmt, DirectiveStmt
+#include "AST/StorageClasses.hpp"  // for Storage::Class
+#include "AST/Type.hpp"            // for Type
+#include "Common/CodeLocation.h"   // for CodeLocation
+#include "Common/Iterate.hpp"      // for reverseIterate
 #include "Common/SemanticError.h"  // for SemanticError
 #include "Common/UniqueName.h"     // for UniqueName
-#include "Common/utility.h"        // for maybeClone, maybeBuild, CodeLocation
+#include "Common/utility.h"        // for maybeClone
 #include "Parser/ParseNode.h"      // for DeclarationNode, ExpressionNode
-#include "SynTree/LinkageSpec.h"   // for Spec, linkageName, Cforall
-#include "SynTree/Attribute.h"     // for Attribute
-#include "SynTree/Declaration.h"   // for TypeDecl, ObjectDecl, InlineMemberDecl, Declaration
-#include "SynTree/Expression.h"    // for Expression, ConstantExpr
-#include "SynTree/Statement.h"     // for AsmStmt
-#include "SynTree/Type.h"          // for Type, Type::StorageClasses, Type::...
 #include "TypeData.h"              // for TypeData, TypeData::Aggregate_t
 #include "TypedefTable.h"          // for TypedefTable
@@ -61,5 +65,5 @@
 UniqueName DeclarationNode::anonymous( "__anonymous" );
 
-extern LinkageSpec::Spec linkage;						// defined in parser.yy
+extern ast::Linkage::Spec linkage;						// defined in parser.yy
 
 DeclarationNode::DeclarationNode() :
@@ -67,5 +71,5 @@
 
 //	variable.name = nullptr;
-	variable.tyClass = TypeDecl::NUMBER_OF_KINDS;
+	variable.tyClass = ast::TypeDecl::NUMBER_OF_KINDS;
 	variable.assertions = nullptr;
 	variable.initializer = nullptr;
@@ -105,6 +109,6 @@
 	newnode->hasEllipsis = hasEllipsis;
 	newnode->linkage = linkage;
-	newnode->asmName = maybeClone( asmName );
-	cloneAll( attributes, newnode->attributes );
+	newnode->asmName = maybeCopy( asmName );
+	newnode->attributes = attributes;
 	newnode->initializer = maybeClone( initializer );
 	newnode->extension = extension;
@@ -118,5 +122,5 @@
 
 	newnode->assert.condition = maybeClone( assert.condition );
-	newnode->assert.message = maybeClone( assert.message );
+	newnode->assert.message = maybeCopy( assert.message );
 	return newnode;
 } // DeclarationNode::clone
@@ -128,10 +132,10 @@
 	} // if
 
-	if ( linkage != LinkageSpec::Cforall ) {
-		os << LinkageSpec::name( linkage ) << " ";
-	} // if
-
-	storageClasses.print( os );
-	funcSpecs.print( os );
+	if ( linkage != ast::Linkage::Cforall ) {
+		os << ast::Linkage::name( linkage ) << " ";
+	} // if
+
+	ast::print( os, storageClasses );
+	ast::print( os, funcSpecs );
 
 	if ( type ) {
@@ -154,5 +158,5 @@
 	if ( ! attributes.empty() ) {
 		os << string( indent + 2, ' ' ) << "with attributes " << endl;
-		for ( Attribute * attr: reverseIterate( attributes ) ) {
+		for ( ast::ptr<ast::Attribute> const & attr : reverseIterate( attributes ) ) {
 			os << string( indent + 4, ' ' ) << attr->name.c_str() << endl;
 		} // for
@@ -169,5 +173,5 @@
 }
 
-DeclarationNode * DeclarationNode::newStorageClass( Type::StorageClasses sc ) {
+DeclarationNode * DeclarationNode::newStorageClass( ast::Storage::Classes sc ) {
 	DeclarationNode * newnode = new DeclarationNode;
 	newnode->storageClasses = sc;
@@ -175,5 +179,5 @@
 } // DeclarationNode::newStorageClass
 
-DeclarationNode * DeclarationNode::newFuncSpecifier( Type::FuncSpecifiers fs ) {
+DeclarationNode * DeclarationNode::newFuncSpecifier( ast::Function::Specs fs ) {
 	DeclarationNode * newnode = new DeclarationNode;
 	newnode->funcSpecs = fs;
@@ -181,5 +185,5 @@
 } // DeclarationNode::newFuncSpecifier
 
-DeclarationNode * DeclarationNode::newTypeQualifier( Type::Qualifiers tq ) {
+DeclarationNode * DeclarationNode::newTypeQualifier( ast::CV::Qualifiers tq ) {
 	DeclarationNode * newnode = new DeclarationNode;
 	newnode->type = new TypeData();
@@ -241,5 +245,5 @@
 }
 
-DeclarationNode * DeclarationNode::newAggregate( AggregateDecl::Aggregate kind, const string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body ) {
+DeclarationNode * DeclarationNode::newAggregate( ast::AggregateDecl::Aggregate kind, const string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body ) {
 	DeclarationNode * newnode = new DeclarationNode;
 	newnode->type = new TypeData( TypeData::Aggregate );
@@ -271,6 +275,4 @@
 } // DeclarationNode::newEnum
 
-
-
 DeclarationNode * DeclarationNode::newName( const string * name ) {
 	DeclarationNode * newnode = new DeclarationNode;
@@ -324,5 +326,5 @@
 } // DeclarationNode::newFromTypeGen
 
-DeclarationNode * DeclarationNode::newTypeParam( TypeDecl::Kind tc, const string * name ) {
+DeclarationNode * DeclarationNode::newTypeParam( ast::TypeDecl::Kind tc, const string * name ) {
 	DeclarationNode * newnode = newName( name );
 	newnode->type = nullptr;
@@ -336,5 +338,5 @@
 	newnode->type = new TypeData( TypeData::Aggregate );
 	newnode->type->aggregate.name = name;
-	newnode->type->aggregate.kind = AggregateDecl::Trait;
+	newnode->type->aggregate.kind = ast::AggregateDecl::Trait;
 	newnode->type->aggregate.params = params;
 	newnode->type->aggregate.fields = asserts;
@@ -346,5 +348,5 @@
 	newnode->type = new TypeData( TypeData::AggregateInst );
 	newnode->type->aggInst.aggregate = new TypeData( TypeData::Aggregate );
-	newnode->type->aggInst.aggregate->aggregate.kind = AggregateDecl::Trait;
+	newnode->type->aggInst.aggregate->aggregate.kind = ast::AggregateDecl::Trait;
 	newnode->type->aggInst.aggregate->aggregate.name = name;
 	newnode->type->aggInst.params = params;
@@ -381,5 +383,5 @@
 	newnode->type->array.dimension = size;
 	newnode->type->array.isStatic = isStatic;
-	if ( newnode->type->array.dimension == nullptr || newnode->type->array.dimension->isExpressionType<ConstantExpr * >() ) {
+	if ( newnode->type->array.dimension == nullptr || newnode->type->array.dimension->isExpressionType<ast::ConstantExpr *>() ) {
 		newnode->type->array.isVarLen = false;
 	} else {
@@ -451,7 +453,8 @@
 	DeclarationNode * newnode = new DeclarationNode;
 	newnode->type = nullptr;
-	std::list< Expression * > exprs;
+	std::vector<ast::ptr<ast::Expr>> exprs;
 	buildList( expr, exprs );
-	newnode->attributes.push_back( new Attribute( *name, exprs ) );
+	newnode->attributes.push_back(
+		new ast::Attribute( *name, std::move( exprs ) ) );
 	delete name;
 	return newnode;
@@ -470,5 +473,5 @@
 }
 
-DeclarationNode * DeclarationNode::newStaticAssert( ExpressionNode * condition, Expression * message ) {
+DeclarationNode * DeclarationNode::newStaticAssert( ExpressionNode * condition, ast::Expr * message ) {
 	DeclarationNode * newnode = new DeclarationNode;
 	newnode->assert.condition = condition;
@@ -477,6 +480,5 @@
 }
 
-
-void appendError( string & dst, const string & src ) {
+static void appendError( string & dst, const string & src ) {
 	if ( src.empty() ) return;
 	if ( dst.empty() ) { dst = src; return; }
@@ -485,38 +487,48 @@
 
 void DeclarationNode::checkQualifiers( const TypeData * src, const TypeData * dst ) {
-	const Type::Qualifiers qsrc = src->qualifiers, qdst = dst->qualifiers; // optimization
-
-	if ( (qsrc & qdst).any() ) {						// duplicates ?
-		for ( unsigned int i = 0; i < Type::NumTypeQualifier; i += 1 ) { // find duplicates
-			if ( qsrc[i] && qdst[i] ) {
-				appendError( error, string( "duplicate " ) + Type::QualifiersNames[i] );
-			} // if
-		} // for
+	const ast::CV::Qualifiers qsrc = src->qualifiers, qdst = dst->qualifiers; // optimization
+	const ast::CV::Qualifiers duplicates = qsrc & qdst;
+
+	if ( duplicates.any() ) {
+		std::stringstream str;
+		str << "duplicate ";
+		ast::print( str, duplicates );
+		str << "qualifier(s)";
+		appendError( error, str.str() );
 	} // for
 } // DeclarationNode::checkQualifiers
 
 void DeclarationNode::checkSpecifiers( DeclarationNode * src ) {
-	if ( (funcSpecs & src->funcSpecs).any() ) {			// duplicates ?
-		for ( unsigned int i = 0; i < Type::NumFuncSpecifier; i += 1 ) { // find duplicates
-			if ( funcSpecs[i] && src->funcSpecs[i] ) {
-				appendError( error, string( "duplicate " ) + Type::FuncSpecifiersNames[i] );
-			} // if
-		} // for
-	} // if
-
-	if ( storageClasses.any() && src->storageClasses.any() ) { // any reason to check ?
-		if ( (storageClasses & src->storageClasses ).any() ) { // duplicates ?
-			for ( unsigned int i = 0; i < Type::NumStorageClass; i += 1 ) { // find duplicates
-				if ( storageClasses[i] && src->storageClasses[i] ) {
-					appendError( error, string( "duplicate " ) + Type::StorageClassesNames[i] );
-				} // if
-			} // for
-			// src is the new item being added and has a single bit
-		} else if ( ! src->storageClasses.is_threadlocal_any() ) { // conflict ?
-			appendError( error, string( "conflicting " )
-				+ Type::StorageClassesNames[storageClasses.ffs()]
-				+ " & " + Type::StorageClassesNames[src->storageClasses.ffs()] );
-			src->storageClasses.reset();				// FIX to preserve invariant of one basic storage specifier
-		} // if
+	ast::Function::Specs fsDups = funcSpecs & src->funcSpecs;
+	if ( fsDups.any() ) {
+		std::stringstream str;
+		str << "duplicate ";
+		ast::print( str, fsDups );
+		str << "function specifier(s)";
+		appendError( error, str.str() );
+	} // if
+
+	// Skip if everything is unset.
+	if ( storageClasses.any() && src->storageClasses.any() ) {
+		ast::Storage::Classes dups = storageClasses & src->storageClasses;
+		// Check for duplicates.
+		if ( dups.any() ) {
+			std::stringstream str;
+			str << "duplicate ";
+			ast::print( str, dups );
+			str << "storage class(es)";
+			appendError( error, str.str() );
+		// Check for conflicts.
+		} else if ( !src->storageClasses.is_threadlocal_any() ) {
+			std::stringstream str;
+			str << "conflicting ";
+			ast::print( str, ast::Storage::Classes( 1 << storageClasses.ffs() ) );
+			str << "& ";
+			ast::print( str, ast::Storage::Classes( 1 << src->storageClasses.ffs() ) );
+			str << "storage classes";
+			appendError( error, str.str() );
+			// FIX to preserve invariant of one basic storage specifier
+			src->storageClasses.reset();
+		}
 	} // if
 
@@ -528,7 +540,11 @@
 	storageClasses |= q->storageClasses;
 
-	for ( Attribute * attr: reverseIterate( q->attributes ) ) {
-		attributes.push_front( attr->clone() );
-	} // for
+	std::vector<ast::ptr<ast::Attribute>> tmp;
+	tmp.reserve( q->attributes.size() );
+	for ( auto const & attr : q->attributes ) {
+		tmp.emplace_back( ast::shallowCopy( attr.get() ) );
+	}
+	spliceBegin( attributes, tmp );
+
 	return this;
 } // DeclarationNode::copySpecifiers
@@ -716,5 +732,5 @@
 
 DeclarationNode * DeclarationNode::addAssertions( DeclarationNode * assertions ) {
-	if ( variable.tyClass != TypeDecl::NUMBER_OF_KINDS ) {
+	if ( variable.tyClass != ast::TypeDecl::NUMBER_OF_KINDS ) {
 		if ( variable.assertions ) {
 			variable.assertions->appendList( assertions );
@@ -798,7 +814,5 @@
 DeclarationNode * DeclarationNode::copyAttribute( DeclarationNode * a ) {
 	if ( a ) {
-		for ( Attribute *attr: reverseIterate( a->attributes ) ) {
-			attributes.push_front( attr );
-		} // for
+		spliceBegin( attributes, a->attributes );
 		a->attributes.clear();
 	} // if
@@ -921,5 +935,5 @@
 
 DeclarationNode * DeclarationNode::addTypeInitializer( DeclarationNode * init ) {
-	assertf( variable.tyClass != TypeDecl::NUMBER_OF_KINDS, "Called addTypeInitializer on something that isn't a type variable." );
+	assertf( variable.tyClass != ast::TypeDecl::NUMBER_OF_KINDS, "Called addTypeInitializer on something that isn't a type variable." );
 	variable.initializer = init;
 	return this;
@@ -985,12 +999,13 @@
 }
 
-void buildList( const DeclarationNode * firstNode, std::list< Declaration * > & outputList ) {
+void buildList( const DeclarationNode * firstNode,
+		std::vector<ast::ptr<ast::Decl>> & outputList ) {
 	SemanticErrorException errors;
-	std::back_insert_iterator< std::list< Declaration * > > out( outputList );
+	std::back_insert_iterator<std::vector<ast::ptr<ast::Decl>>> out( outputList );
 
 	for ( const DeclarationNode * cur = firstNode; cur; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ) ) {
 		try {
 			bool extracted = false, anon = false;
-			AggregateDecl * unionDecl = nullptr;
+			ast::AggregateDecl * unionDecl = nullptr;
 
 			if ( DeclarationNode * extr = cur->extractAggregate() ) {
@@ -1029,8 +1044,8 @@
 				} // if
 
-				Declaration * decl = extr->build();
+				ast::Decl * decl = extr->build();
 				if ( decl ) {
 					// Remember the declaration if it is a union aggregate ?
-					unionDecl = dynamic_cast<UnionDecl *>( decl );
+					unionDecl = dynamic_cast<ast::UnionDecl *>( decl );
 
 					decl->location = cur->location;
@@ -1051,7 +1066,7 @@
 			} // if
 
-			Declaration * decl = cur->build();
+			ast::Decl * decl = cur->build();
 			if ( decl ) {
-				if ( TypedefDecl * typedefDecl = dynamic_cast<TypedefDecl *>( decl ) ) {
+				if ( auto typedefDecl = dynamic_cast<ast::TypedefDecl *>( decl ) ) {
 					if ( unionDecl ) {					// is the typedef alias a union aggregate ?
 						// This code handles a special issue with the attribute transparent_union.
@@ -1065,17 +1080,17 @@
 
 						// If typedef is an alias for a union, then its alias type was hoisted above and remembered.
-						if ( UnionInstType * unionInstType = dynamic_cast<UnionInstType *>( typedefDecl->base ) ) {
+						if ( auto unionInstType = typedefDecl->base.as<ast::UnionInstType>() ) {
+							auto instType = ast::mutate( unionInstType );
 							// Remove all transparent_union attributes from typedef and move to alias union.
-							list<Attribute *>::iterator attr;
-							for ( attr = unionInstType->attributes.begin(); attr != unionInstType->attributes.end(); ) { // forward order
+							for ( auto attr = instType->attributes.begin() ; attr != instType->attributes.end() ; ) { // forward order
+								assert( *attr );
 								if ( (*attr)->name == "transparent_union" || (*attr)->name == "__transparent_union__" ) {
-									list<Attribute *>::iterator cur = attr; // remember current node
-									attr++;				// advance iterator
-									unionDecl->attributes.emplace_back( *cur ); // move current
-									unionInstType->attributes.erase( cur ); // remove current
+									unionDecl->attributes.emplace_back( attr->release() );
+									attr = instType->attributes.erase( attr );
 								} else {
-									attr++;				// advance iterator
+									attr++;
 								} // if
 							} // for
+							typedefDecl->base = instType;
 						} // if
 					} // if
@@ -1090,6 +1105,6 @@
 				if ( ! (extracted && decl->name == "" && ! anon && ! cur->get_inLine()) ) {
 					if ( decl->name == "" ) {
-						if ( DeclarationWithType * dwt = dynamic_cast<DeclarationWithType *>( decl ) ) {
-							if ( ReferenceToType * aggr = dynamic_cast<ReferenceToType *>( dwt->get_type() ) ) {
+						if ( auto dwt = dynamic_cast<ast::DeclWithType *>( decl ) ) {
+							if ( auto aggr = dynamic_cast<ast::BaseInstType const *>( dwt->get_type() ) ) {
 								if ( aggr->name.find("anonymous") == std::string::npos ) {
 									if ( ! cur->get_inLine() ) {
@@ -1117,33 +1132,39 @@
 
 // currently only builds assertions, function parameters, and return values
-void buildList( const DeclarationNode * firstNode, std::list< DeclarationWithType * > & outputList ) {
+void buildList( const DeclarationNode * firstNode, std::vector<ast::ptr<ast::DeclWithType>> & outputList ) {
 	SemanticErrorException errors;
-	std::back_insert_iterator< std::list< DeclarationWithType * > > out( outputList );
+	std::back_insert_iterator<std::vector<ast::ptr<ast::DeclWithType>>> out( outputList );
 
 	for ( const DeclarationNode * cur = firstNode; cur; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ) ) {
 		try {
-			Declaration * decl = cur->build();
+			ast::Decl * decl = cur->build();
 			assert( decl );
-			if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) {
+			if ( ast::DeclWithType * dwt = dynamic_cast<ast::DeclWithType *>( decl ) ) {
 				dwt->location = cur->location;
 				*out++ = dwt;
-			} else if ( StructDecl * agg = dynamic_cast< StructDecl * >( decl ) ) {
+			} else if ( ast::StructDecl * agg = dynamic_cast<ast::StructDecl *>( decl ) ) {
 				// e.g., int foo(struct S) {}
-				StructInstType * inst = new StructInstType( Type::Qualifiers(), agg->name );
-				auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
-				obj->location = cur->location;
+				auto inst = new ast::StructInstType( agg->name );
+				auto obj = new ast::ObjectDecl( cur->location, "", inst );
+				obj->linkage = linkage;
 				*out++ = obj;
 				delete agg;
-			} else if ( UnionDecl * agg = dynamic_cast< UnionDecl * >( decl ) ) {
+			} else if ( ast::UnionDecl * agg = dynamic_cast<ast::UnionDecl *>( decl ) ) {
 				// e.g., int foo(union U) {}
-				UnionInstType * inst = new UnionInstType( Type::Qualifiers(), agg->name );
-				auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
-				obj->location = cur->location;
+				auto inst = new ast::UnionInstType( agg->name );
+				auto obj = new ast::ObjectDecl( cur->location,
+					"", inst, nullptr, ast::Storage::Classes(),
+					linkage );
 				*out++ = obj;
-			} else if ( EnumDecl * agg = dynamic_cast< EnumDecl * >( decl ) ) {
+			} else if ( ast::EnumDecl * agg = dynamic_cast<ast::EnumDecl *>( decl ) ) {
 				// e.g., int foo(enum E) {}
-				EnumInstType * inst = new EnumInstType( Type::Qualifiers(), agg->name );
-				auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
-				obj->location = cur->location;
+				auto inst = new ast::EnumInstType( agg->name );
+				auto obj = new ast::ObjectDecl( cur->location,
+					"",
+					inst,
+					nullptr,
+					ast::Storage::Classes(),
+					linkage
+				);
 				*out++ = obj;
 			} // if
@@ -1158,7 +1179,8 @@
 } // buildList
 
-void buildTypeList( const DeclarationNode * firstNode, std::list< Type * > & outputList ) {
+void buildTypeList( const DeclarationNode * firstNode,
+		std::vector<ast::ptr<ast::Type>> & outputList ) {
 	SemanticErrorException errors;
-	std::back_insert_iterator< std::list< Type * > > out( outputList );
+	std::back_insert_iterator<std::vector<ast::ptr<ast::Type>>> out( outputList );
 	const DeclarationNode * cur = firstNode;
 
@@ -1177,21 +1199,30 @@
 } // buildTypeList
 
-Declaration * DeclarationNode::build() const {
+ast::Decl * DeclarationNode::build() const {
 	if ( ! error.empty() ) SemanticError( this, error + " in declaration of " );
 
 	if ( asmStmt ) {
-		return new AsmDecl( strict_dynamic_cast<AsmStmt *>( asmStmt->build() ) );
+		auto stmt = strict_dynamic_cast<ast::AsmStmt *>( asmStmt->build() );
+		return new ast::AsmDecl( stmt->location, stmt );
 	} // if
 	if ( directiveStmt ) {
-		return new DirectiveDecl( strict_dynamic_cast<DirectiveStmt *>( directiveStmt->build() ) );
-	} // if
-
-	if ( variable.tyClass != TypeDecl::NUMBER_OF_KINDS ) {
+		auto stmt = strict_dynamic_cast<ast::DirectiveStmt *>( directiveStmt->build() );
+		return new ast::DirectiveDecl( stmt->location, stmt );
+	} // if
+
+	if ( variable.tyClass != ast::TypeDecl::NUMBER_OF_KINDS ) {
 		// otype is internally converted to dtype + otype parameters
-		static const TypeDecl::Kind kindMap[] = { TypeDecl::Dtype, TypeDecl::Dtype, TypeDecl::Dtype, TypeDecl::Ftype, TypeDecl::Ttype, TypeDecl::Dimension };
-		static_assert( sizeof(kindMap) / sizeof(kindMap[0]) == TypeDecl::NUMBER_OF_KINDS, "DeclarationNode::build: kindMap is out of sync." );
+		static const ast::TypeDecl::Kind kindMap[] = { ast::TypeDecl::Dtype, ast::TypeDecl::Dtype, ast::TypeDecl::Dtype, ast::TypeDecl::Ftype, ast::TypeDecl::Ttype, ast::TypeDecl::Dimension };
+		static_assert( sizeof(kindMap) / sizeof(kindMap[0]) == ast::TypeDecl::NUMBER_OF_KINDS, "DeclarationNode::build: kindMap is out of sync." );
 		assertf( variable.tyClass < sizeof(kindMap)/sizeof(kindMap[0]), "Variable's tyClass is out of bounds." );
-		TypeDecl * ret = new TypeDecl( *name, Type::StorageClasses(), nullptr, kindMap[ variable.tyClass ], variable.tyClass == TypeDecl::Otype || variable.tyClass == TypeDecl::DStype, variable.initializer ? variable.initializer->buildType() : nullptr );
-		buildList( variable.assertions, ret->get_assertions() );
+		ast::TypeDecl * ret = new ast::TypeDecl( location,
+			*name,
+			ast::Storage::Classes(),
+			(ast::Type *)nullptr,
+			kindMap[ variable.tyClass ],
+			variable.tyClass == ast::TypeDecl::Otype || variable.tyClass == ast::TypeDecl::DStype,
+			variable.initializer ? variable.initializer->buildType() : nullptr
+		);
+		buildList( variable.assertions, ret->assertions );
 		return ret;
 	} // if
@@ -1215,7 +1246,17 @@
 		} // if
 		bool isDelete = initializer && initializer->get_isDelete();
-		Declaration * decl = buildDecl( type, name ? *name : string( "" ), storageClasses, maybeBuild( bitfieldWidth ), funcSpecs, linkage, asmName, isDelete ? nullptr : maybeBuild(initializer), attributes )->set_extension( extension );
+		ast::Decl * decl = buildDecl(
+			type,
+			name ? *name : string( "" ),
+			storageClasses,
+			maybeBuild( bitfieldWidth ),
+			funcSpecs,
+			linkage,
+			asmName,
+			isDelete ? nullptr : maybeBuild( initializer ),
+			copy( attributes )
+		)->set_extension( extension );
 		if ( isDelete ) {
-			DeclarationWithType * dwt = strict_dynamic_cast<DeclarationWithType *>( decl );
+			auto dwt = strict_dynamic_cast<ast::DeclWithType *>( decl );
 			dwt->isDeleted = true;
 		}
@@ -1224,5 +1265,7 @@
 
 	if ( assert.condition ) {
-		return new StaticAssertDecl( maybeBuild( assert.condition ), strict_dynamic_cast< ConstantExpr * >( maybeClone( assert.message ) ) );
+		auto cond = maybeBuild( assert.condition );
+		auto msg = strict_dynamic_cast<ast::ConstantExpr *>( maybeCopy( assert.message ) );
+		return new ast::StaticAssertDecl( location, cond, msg );
 	}
 
@@ -1235,11 +1278,22 @@
 	} // if
 	if ( enumInLine ) {
-		return new InlineMemberDecl( *name, storageClasses, linkage, nullptr );
+		return new ast::InlineMemberDecl( location,
+			*name, (ast::Type*)nullptr, storageClasses, linkage );
 	} // if
 	assertf( name, "ObjectDecl must a have name\n" );
-	return (new ObjectDecl( *name, storageClasses, linkage, maybeBuild( bitfieldWidth ), nullptr, maybeBuild( initializer ) ))->set_asmName( asmName )->set_extension( extension );
-}
-
-Type * DeclarationNode::buildType() const {
+	auto ret = new ast::ObjectDecl( location,
+		*name,
+		(ast::Type*)nullptr,
+		maybeBuild( initializer ),
+		storageClasses,
+		linkage,
+		maybeBuild( bitfieldWidth )
+	);
+	ret->asmName = asmName;
+	ret->extension = extension;
+	return ret;
+}
+
+ast::Type * DeclarationNode::buildType() const {
 	assert( type );
 
@@ -1247,16 +1301,23 @@
 	case TypeData::Enum:
 	case TypeData::Aggregate: {
-		ReferenceToType * ret = buildComAggInst( type, attributes, linkage );
-		buildList( type->aggregate.actuals, ret->get_parameters() );
+		ast::BaseInstType * ret =
+			buildComAggInst( type, copy( attributes ), linkage );
+		buildList( type->aggregate.actuals, ret->params );
 		return ret;
 	}
 	case TypeData::Symbolic: {
-		TypeInstType * ret = new TypeInstType( buildQualifiers( type ), *type->symbolic.name, false, attributes );
-		buildList( type->symbolic.actuals, ret->get_parameters() );
+		ast::TypeInstType * ret = new ast::TypeInstType(
+			*type->symbolic.name,
+			// This is just a default, the true value is not known yet.
+			ast::TypeDecl::Dtype,
+			buildQualifiers( type ),
+			copy( attributes ) );
+		buildList( type->symbolic.actuals, ret->params );
 		return ret;
 	}
 	default:
-		Type * simpletypes = typebuild( type );
-		simpletypes->get_attributes() = attributes;		// copy because member is const
+		ast::Type * simpletypes = typebuild( type );
+		// copy because member is const
+		simpletypes->attributes = attributes;
 		return simpletypes;
 	} // switch
Index: src/Parser/ExpressionNode.cc
===================================================================
--- src/Parser/ExpressionNode.cc	(revision 70056edafe6b115773f5da41e81a7b2adf5c08f5)
+++ src/Parser/ExpressionNode.cc	(revision e02e13fc53b4a6d659a7753b2c843a4b7e203c0d)
@@ -10,6 +10,6 @@
 // Created On       : Sat May 16 13:17:07 2015
 // Last Modified By : Andrew Beach
-// Last Modified On : Tue Mar 14 12:00:00 2023
-// Update Count     : 1082
+// Last Modified On : Tue Apr  4 11:07:00 2023
+// Update Count     : 1083
 //
 
@@ -21,15 +21,10 @@
 #include <string>                  // for string, operator+, operator==
 
+#include "AST/Expr.hpp"            // for NameExpr
+#include "AST/Type.hpp"            // for BaseType, SueInstType
 #include "Common/SemanticError.h"  // for SemanticError
 #include "Common/utility.h"        // for maybeMoveBuild, maybeBuild, CodeLo...
 #include "ParseNode.h"             // for ExpressionNode, maybeMoveBuildType
-#include "SynTree/Constant.h"      // for Constant
-#include "SynTree/Declaration.h"   // for EnumDecl, StructDecl, UnionDecl
-#include "SynTree/Expression.h"    // for Expression, ConstantExpr, NameExpr
-#include "SynTree/Statement.h"     // for CompoundStmt, Statement
-#include "SynTree/Type.h"          // for BasicType, Type, Type::Qualifiers
 #include "parserutility.h"         // for notZeroExpr
-
-class Initializer;
 
 using namespace std;
@@ -48,6 +43,4 @@
 // because the CONT rule is NOT triggered if the pattern is empty. Hence, constants are reparsed here to determine their
 // type.
-
-extern const Type::Qualifiers noQualifiers;				// no qualifiers on constants
 
 // static inline bool checkH( char c ) { return c == 'h' || c == 'H'; }
@@ -127,9 +120,10 @@
 } // scanbin
 
-Expression * build_constantInteger( string & str ) {
-	static const BasicType::Kind kind[2][6] = {
+ast::Expr * build_constantInteger(
+		const CodeLocation & location, string & str ) {
+	static const ast::BasicType::Kind kind[2][6] = {
 		// short (h) must be before char (hh) because shorter type has the longer suffix
-		{ BasicType::ShortSignedInt, BasicType::SignedChar, BasicType::SignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt, /* BasicType::SignedInt128 */ BasicType::LongLongSignedInt, },
-		{ BasicType::ShortUnsignedInt, BasicType::UnsignedChar, BasicType::UnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongUnsignedInt, /* BasicType::UnsignedInt128 */ BasicType::LongLongUnsignedInt, },
+		{ ast::BasicType::ShortSignedInt, ast::BasicType::SignedChar, ast::BasicType::SignedInt, ast::BasicType::LongSignedInt, ast::BasicType::LongLongSignedInt, /* BasicType::SignedInt128 */ ast::BasicType::LongLongSignedInt, },
+		{ ast::BasicType::ShortUnsignedInt, ast::BasicType::UnsignedChar, ast::BasicType::UnsignedInt, ast::BasicType::LongUnsignedInt, ast::BasicType::LongLongUnsignedInt, /* BasicType::UnsignedInt128 */ ast::BasicType::LongLongUnsignedInt, },
 	};
 
@@ -141,5 +135,5 @@
 	string str2( "0x0" );
 	unsigned long long int v, v2 = 0;					// converted integral value
-	Expression * ret, * ret2;
+	ast::Expr * ret, * ret2;
 
 	int type = -1;										// 0 => short, 1 => char, 2 => int, 3 => long int, 4 => long long int, 5 => int128
@@ -149,9 +143,9 @@
 	// special constants
 	if ( str == "0" ) {
-		ret = new ConstantExpr( Constant( (Type *)new ZeroType( noQualifiers ), str, (unsigned long long int)0 ) );
+		ret = new ast::ConstantExpr( location, new ast::ZeroType(), str, 0 );
 		goto CLEANUP;
 	} // if
 	if ( str == "1" ) {
-		ret = new ConstantExpr( Constant( (Type *)new OneType( noQualifiers ), str, (unsigned long long int)1 ) );
+		ret = new ast::ConstantExpr( location, new ast::OneType(), str, 1 );
 		goto CLEANUP;
 	} // if
@@ -304,19 +298,36 @@
 
 	// Constant type is correct for overload resolving.
-	ret = new ConstantExpr( Constant( new BasicType( noQualifiers, kind[Unsigned][type] ), str, v ) );
+	ret = new ast::ConstantExpr( location,
+		new ast::BasicType( kind[Unsigned][type] ), str, v );
 	if ( Unsigned && type < 2 ) {						// hh or h, less than int ?
 		// int i = -1uh => 65535 not -1, so cast is necessary for unsigned, which unfortunately eliminates warnings for large values.
-		ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][type] ), false );
+		ret = new ast::CastExpr( location,
+			ret,
+			new ast::BasicType( kind[Unsigned][type] ),
+			ast::ExplicitCast );
 	} else if ( ltype != -1 ) {							// explicit length ?
 		if ( ltype == 6 ) {								// int128, (int128)constant
-//			ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][type] ), false );
-			ret2 = new ConstantExpr( Constant( new BasicType( noQualifiers, BasicType::LongLongSignedInt ), str2, v2 ) );
-			ret = build_compoundLiteral(
-				DeclarationNode::newBasicType( DeclarationNode::Int128 )->addType( DeclarationNode::newSignedNess( DeclarationNode::Unsigned ) ),
-				new InitializerNode( (InitializerNode *)(new InitializerNode( new ExpressionNode( v2 == 0 ? ret2 : ret ) ))->set_last( new InitializerNode( new ExpressionNode( v2 == 0 ? ret : ret2 ) ) ), true ) );
+			ret2 = new ast::ConstantExpr( location,
+				new ast::BasicType( ast::BasicType::LongLongSignedInt ),
+				str2,
+				v2 );
+			ret = build_compoundLiteral( location,
+				DeclarationNode::newBasicType(
+					DeclarationNode::Int128
+				)->addType(
+					DeclarationNode::newSignedNess( DeclarationNode::Unsigned ) ),
+				new InitializerNode(
+					(InitializerNode *)(new InitializerNode( new ExpressionNode( v2 == 0 ? ret2 : ret ) ))->set_last( new InitializerNode( new ExpressionNode( v2 == 0 ? ret : ret2 ) ) ), true )
+			);
 		} else {										// explicit length, (length_type)constant
-			ret = new CastExpr( ret, new TypeInstType( Type::Qualifiers(), lnthsInt[Unsigned][ltype], false ), false );
+			ret = new ast::CastExpr( location,
+				ret,
+				new ast::TypeInstType( lnthsInt[Unsigned][ltype], ast::TypeDecl::Dtype ),
+				ast::ExplicitCast );
 			if ( ltype == 5 ) {							// pointer, intptr( (uintptr_t)constant )
-				ret = build_func( new ExpressionNode( build_varref( new string( "intptr" ) ) ), new ExpressionNode( ret ) );
+				ret = build_func( location,
+					new ExpressionNode(
+						build_varref( location, new string( "intptr" ) ) ),
+					new ExpressionNode( ret ) );
 			} // if
 		} // if
@@ -362,8 +373,9 @@
 
 
-Expression * build_constantFloat( string & str ) {
-	static const BasicType::Kind kind[2][12] = {
-		{ BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::uuFloat80, BasicType::uuFloat128, BasicType::uFloat16, BasicType::uFloat32, BasicType::uFloat32x, BasicType::uFloat64, BasicType::uFloat64x, BasicType::uFloat128, BasicType::uFloat128x },
-		{ BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::NUMBER_OF_BASIC_TYPES, BasicType::NUMBER_OF_BASIC_TYPES, BasicType::uFloat16Complex, BasicType::uFloat32Complex, BasicType::uFloat32xComplex, BasicType::uFloat64Complex, BasicType::uFloat64xComplex, BasicType::uFloat128Complex, BasicType::uFloat128xComplex },
+ast::Expr * build_constantFloat(
+		const CodeLocation & location, string & str ) {
+	static const ast::BasicType::Kind kind[2][12] = {
+		{ ast::BasicType::Float, ast::BasicType::Double, ast::BasicType::LongDouble, ast::BasicType::uuFloat80, ast::BasicType::uuFloat128, ast::BasicType::uFloat16, ast::BasicType::uFloat32, ast::BasicType::uFloat32x, ast::BasicType::uFloat64, ast::BasicType::uFloat64x, ast::BasicType::uFloat128, ast::BasicType::uFloat128x },
+		{ ast::BasicType::FloatComplex, ast::BasicType::DoubleComplex, ast::BasicType::LongDoubleComplex, ast::BasicType::NUMBER_OF_BASIC_TYPES, ast::BasicType::NUMBER_OF_BASIC_TYPES, ast::BasicType::uFloat16Complex, ast::BasicType::uFloat32Complex, ast::BasicType::uFloat32xComplex, ast::BasicType::uFloat64Complex, ast::BasicType::uFloat64xComplex, ast::BasicType::uFloat128Complex, ast::BasicType::uFloat128xComplex },
 	};
 
@@ -402,7 +414,14 @@
 
 	assert( 0 <= type && type < 12 );
-	Expression * ret = new ConstantExpr( Constant( new BasicType( noQualifiers, kind[complx][type] ), str, v ) );
-	if ( explnth ) {									// explicit length ?
-		ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[complx][type] ), false );
+	ast::Expr * ret = new ast::ConstantExpr( location,
+		new ast::BasicType( kind[complx][type] ),
+		str,
+		v );
+	// explicit length ?
+	if ( explnth ) {
+		ret = new ast::CastExpr( location,
+			ret,
+			new ast::BasicType( kind[complx][type] ),
+			ast::ExplicitCast );
 	} // if
 
@@ -419,11 +438,16 @@
 } // sepString
 
-Expression * build_constantChar( string & str ) {
+ast::Expr * build_constantChar( const CodeLocation & location, string & str ) {
 	string units;										// units
 	sepString( str, units, '\'' );						// separate constant from units
 
-	Expression * ret = new ConstantExpr( Constant( new BasicType( noQualifiers, BasicType::Char ), str, (unsigned long long int)(unsigned char)str[1] ) );
+	ast::Expr * ret = new ast::ConstantExpr( location,
+		new ast::BasicType( ast::BasicType::Char ),
+		str,
+		(unsigned long long int)(unsigned char)str[1] );
 	if ( units.length() != 0 ) {
-		ret = new UntypedExpr( new NameExpr( units ), { ret } );
+		ret = new ast::UntypedExpr( location,
+			new ast::NameExpr( location, units ),
+			{ ret } );
 	} // if
 
@@ -432,32 +456,39 @@
 } // build_constantChar
 
-Expression * build_constantStr( string & str ) {
+ast::Expr * build_constantStr(
+		const CodeLocation & location,
+		string & str ) {
 	assert( str.length() > 0 );
 	string units;										// units
 	sepString( str, units, '"' );						// separate constant from units
 
-	Type * strtype;
+	ast::Type * strtype;
 	switch ( str[0] ) {									// str has >= 2 characters, i.e, null string "" => safe to look at subscripts 0/1
 	case 'u':
 		if ( str[1] == '8' ) goto Default;				// utf-8 characters => array of char
 		// lookup type of associated typedef
-		strtype = new TypeInstType( Type::Qualifiers( ), "char16_t", false );
+		strtype = new ast::TypeInstType( "char16_t", ast::TypeDecl::Dtype );
 		break;
 	case 'U':
-		strtype = new TypeInstType( Type::Qualifiers( ), "char32_t", false );
+		strtype = new ast::TypeInstType( "char32_t", ast::TypeDecl::Dtype );
 		break;
 	case 'L':
-		strtype = new TypeInstType( Type::Qualifiers( ), "wchar_t", false );
+		strtype = new ast::TypeInstType( "wchar_t", ast::TypeDecl::Dtype );
 		break;
 	Default:											// char default string type
 	default:
-		strtype = new BasicType( Type::Qualifiers( ), BasicType::Char );
+		strtype = new ast::BasicType( ast::BasicType::Char );
 	} // switch
-	ArrayType * at = new ArrayType( noQualifiers, strtype,
-									new ConstantExpr( Constant::from_ulong( str.size() + 1 - 2 ) ), // +1 for '\0' and -2 for '"'
-									false, false );
-	Expression * ret = new ConstantExpr( Constant( at, str, std::nullopt ) );
+	ast::ArrayType * at = new ast::ArrayType(
+		strtype,
+		// Length is adjusted: +1 for '\0' and -2 for '"'
+		ast::ConstantExpr::from_ulong( location, str.size() + 1 - 2 ),
+		ast::FixedLen,
+		ast::DynamicDim );
+	ast::Expr * ret = new ast::ConstantExpr( location, at, str, std::nullopt );
 	if ( units.length() != 0 ) {
-		ret = new UntypedExpr( new NameExpr( units ), { ret } );
+		ret = new ast::UntypedExpr( location,
+			new ast::NameExpr( location, units ),
+			{ ret } );
 	} // if
 
@@ -466,19 +497,24 @@
 } // build_constantStr
 
-Expression * build_field_name_FLOATING_FRACTIONconstant( const string & str ) {
+ast::Expr * build_field_name_FLOATING_FRACTIONconstant(
+		const CodeLocation & location, const string & str ) {
 	if ( str.find_first_not_of( "0123456789", 1 ) != string::npos ) SemanticError( yylloc, "invalid tuple index " + str );
-	Expression * ret = build_constantInteger( *new string( str.substr(1) ) );
+	ast::Expr * ret = build_constantInteger( location,
+		*new string( str.substr(1) ) );
 	delete &str;
 	return ret;
 } // build_field_name_FLOATING_FRACTIONconstant
 
-Expression * build_field_name_FLOATING_DECIMALconstant( const string & str ) {
+ast::Expr * build_field_name_FLOATING_DECIMALconstant(
+		const CodeLocation & location, const string & str ) {
 	if ( str[str.size() - 1] != '.' ) SemanticError( yylloc, "invalid tuple index " + str );
-	Expression * ret = build_constantInteger( *new string( str.substr( 0, str.size()-1 ) ) );
+	ast::Expr * ret = build_constantInteger(
+		location, *new string( str.substr( 0, str.size()-1 ) ) );
 	delete &str;
 	return ret;
 } // build_field_name_FLOATING_DECIMALconstant
 
-Expression * build_field_name_FLOATINGconstant( const string & str ) {
+ast::Expr * build_field_name_FLOATINGconstant( const CodeLocation & location,
+		const string & str ) {
 	// str is of the form A.B -> separate at the . and return member expression
 	int a, b;
@@ -486,51 +522,63 @@
 	stringstream ss( str );
 	ss >> a >> dot >> b;
-	UntypedMemberExpr * ret = new UntypedMemberExpr( new ConstantExpr( Constant::from_int( b ) ), new ConstantExpr( Constant::from_int( a ) ) );
+	auto ret = new ast::UntypedMemberExpr( location,
+		ast::ConstantExpr::from_int( location, b ),
+		ast::ConstantExpr::from_int( location, a )
+	);
 	delete &str;
 	return ret;
 } // build_field_name_FLOATINGconstant
 
-Expression * make_field_name_fraction_constants( Expression * fieldName, Expression * fracts ) {
-	if ( fracts ) {
-		if ( UntypedMemberExpr * memberExpr = dynamic_cast< UntypedMemberExpr * >( fracts ) ) {
-			memberExpr->set_member( make_field_name_fraction_constants( fieldName, memberExpr->get_aggregate() ) );
-			return memberExpr;
-		} else {
-			return new UntypedMemberExpr( fracts, fieldName );
-		} // if
-	} // if
-	return fieldName;
+ast::Expr * make_field_name_fraction_constants( const CodeLocation & location,
+		ast::Expr * fieldName,
+		ast::Expr * fracts ) {
+	if ( nullptr == fracts ) {
+		return fieldName;
+	} else if ( auto memberExpr = dynamic_cast<ast::UntypedMemberExpr *>( fracts ) ) {
+		memberExpr->member = make_field_name_fraction_constants( location,
+			fieldName,
+			ast::mutate( memberExpr->aggregate.get() ) );
+		return memberExpr;
+	} else {
+		return new ast::UntypedMemberExpr( location, fracts, fieldName );
+	} // if
 } // make_field_name_fraction_constants
 
-Expression * build_field_name_fraction_constants( Expression * fieldName, ExpressionNode * fracts ) {
-	return make_field_name_fraction_constants( fieldName, maybeMoveBuild( fracts ) );
+ast::Expr * build_field_name_fraction_constants( const CodeLocation & location,
+		ast::Expr * fieldName,
+		ExpressionNode * fracts ) {
+	return make_field_name_fraction_constants( location, fieldName, maybeMoveBuild( fracts ) );
 } // build_field_name_fraction_constants
 
-NameExpr * build_varref( const string * name ) {
-	NameExpr * expr = new NameExpr( *name );
+ast::NameExpr * build_varref( const CodeLocation & location,
+		const string * name ) {
+	ast::NameExpr * expr = new ast::NameExpr( location, *name );
 	delete name;
 	return expr;
 } // build_varref
 
-QualifiedNameExpr * build_qualified_expr( const DeclarationNode * decl_node, const NameExpr * name ) {
-	Declaration * newDecl = maybeBuild(decl_node);
-	if ( DeclarationWithType * newDeclWithType = dynamic_cast< DeclarationWithType * >( newDecl ) ) {
-		const Type * t = newDeclWithType->get_type();
-		if ( t ) {
-			if ( const TypeInstType * typeInst = dynamic_cast<const TypeInstType *>( t ) ) {
-				newDecl= new EnumDecl( typeInst->name );
+ast::QualifiedNameExpr * build_qualified_expr( const CodeLocation & location,
+		const DeclarationNode * decl_node,
+		const ast::NameExpr * name ) {
+	ast::Decl * newDecl = maybeBuild( decl_node );
+	if ( ast::DeclWithType * newDeclWithType = dynamic_cast<ast::DeclWithType *>( newDecl ) ) {
+		if ( const ast::Type * t = newDeclWithType->get_type() ) {
+			if ( auto typeInst = dynamic_cast<const ast::TypeInstType *>( t ) ) {
+				newDecl = new ast::EnumDecl( location, typeInst->name );
 			}
 		}
 	}
-	return new QualifiedNameExpr( newDecl, name->name );
+	return new ast::QualifiedNameExpr( location, newDecl, name->name );
 }
 
-QualifiedNameExpr * build_qualified_expr( const EnumDecl * decl_node, const NameExpr * name ) {
-	EnumDecl * newDecl = const_cast< EnumDecl * >( decl_node );
-	return new QualifiedNameExpr( newDecl, name->name );
+ast::QualifiedNameExpr * build_qualified_expr( const CodeLocation & location,
+		const ast::EnumDecl * decl,
+		const ast::NameExpr * name ) {
+	return new ast::QualifiedNameExpr( location, decl, name->name );
 }
 
-DimensionExpr * build_dimensionref( const string * name ) {
-	DimensionExpr * expr = new DimensionExpr( *name );
+ast::DimensionExpr * build_dimensionref( const CodeLocation & location,
+		const string * name ) {
+	ast::DimensionExpr * expr = new ast::DimensionExpr( location, *name );
 	delete name;
 	return expr;
@@ -548,102 +596,183 @@
 }; // OperName
 
-Expression * build_cast( DeclarationNode * decl_node, ExpressionNode * expr_node ) {
-	Type * targetType = maybeMoveBuildType( decl_node );
-	if ( dynamic_cast< VoidType * >( targetType ) ) {
+ast::Expr * build_cast( const CodeLocation & location,
+		DeclarationNode * decl_node,
+		ExpressionNode * expr_node ) {
+	ast::Type * targetType = maybeMoveBuildType( decl_node );
+	if ( dynamic_cast<ast::VoidType *>( targetType ) ) {
 		delete targetType;
-		return new CastExpr( maybeMoveBuild( expr_node ), false );
+		return new ast::CastExpr( location,
+			maybeMoveBuild( expr_node ),
+			ast::ExplicitCast );
 	} else {
-		return new CastExpr( maybeMoveBuild( expr_node ), targetType, false );
+		return new ast::CastExpr( location,
+			maybeMoveBuild( expr_node ),
+			targetType,
+			ast::ExplicitCast );
 	} // if
 } // build_cast
 
-Expression * build_keyword_cast( AggregateDecl::Aggregate target, ExpressionNode * expr_node ) {
-	return new KeywordCastExpr( maybeMoveBuild( expr_node ), target );
+ast::Expr * build_keyword_cast( const CodeLocation & location,
+		ast::AggregateDecl::Aggregate target,
+		ExpressionNode * expr_node ) {
+	return new ast::KeywordCastExpr( location,
+		maybeMoveBuild( expr_node ),
+		target
+	);
 }
 
-Expression * build_virtual_cast( DeclarationNode * decl_node, ExpressionNode * expr_node ) {
-	return new VirtualCastExpr( maybeMoveBuild( expr_node ), maybeMoveBuildType( decl_node ) );
+ast::Expr * build_virtual_cast( const CodeLocation & location,
+		DeclarationNode * decl_node,
+		ExpressionNode * expr_node ) {
+	return new ast::VirtualCastExpr( location,
+		maybeMoveBuild( expr_node ),
+		maybeMoveBuildType( decl_node )
+	);
 } // build_virtual_cast
 
-Expression * build_fieldSel( ExpressionNode * expr_node, Expression * member ) {
-	return new UntypedMemberExpr( member, maybeMoveBuild( expr_node ) );
+ast::Expr * build_fieldSel( const CodeLocation & location,
+		ExpressionNode * expr_node,
+		ast::Expr * member ) {
+	return new ast::UntypedMemberExpr( location,
+		member,
+		maybeMoveBuild( expr_node )
+	);
 } // build_fieldSel
 
-Expression * build_pfieldSel( ExpressionNode * expr_node, Expression * member ) {
-	UntypedExpr * deref = new UntypedExpr( new NameExpr( "*?" ) );
+ast::Expr * build_pfieldSel( const CodeLocation & location,
+		ExpressionNode * expr_node,
+		ast::Expr * member ) {
+	auto deref = new ast::UntypedExpr( location,
+		new ast::NameExpr( location, "*?" )
+	);
 	deref->location = expr_node->location;
-	deref->get_args().push_back( maybeMoveBuild( expr_node ) );
-	UntypedMemberExpr * ret = new UntypedMemberExpr( member, deref );
+	deref->args.push_back( maybeMoveBuild( expr_node ) );
+	auto ret = new ast::UntypedMemberExpr( location, member, deref );
 	return ret;
 } // build_pfieldSel
 
-Expression * build_offsetOf( DeclarationNode * decl_node, NameExpr * member ) {
-	Expression * ret = new UntypedOffsetofExpr( maybeMoveBuildType( decl_node ), member->get_name() );
+ast::Expr * build_offsetOf( const CodeLocation & location,
+		DeclarationNode * decl_node,
+		ast::NameExpr * member ) {
+	ast::Expr * ret = new ast::UntypedOffsetofExpr( location,
+		maybeMoveBuildType( decl_node ),
+		member->name
+	);
+	ret->result = new ast::BasicType( ast::BasicType::LongUnsignedInt );
 	delete member;
 	return ret;
 } // build_offsetOf
 
-Expression * build_and_or( ExpressionNode * expr_node1, ExpressionNode * expr_node2, bool kind ) {
-	return new LogicalExpr( notZeroExpr( maybeMoveBuild( expr_node1 ) ), notZeroExpr( maybeMoveBuild( expr_node2 ) ), kind );
+ast::Expr * build_and_or( const CodeLocation & location,
+		ExpressionNode * expr_node1,
+		ExpressionNode * expr_node2,
+		ast::LogicalFlag flag ) {
+	return new ast::LogicalExpr( location,
+		notZeroExpr( maybeMoveBuild( expr_node1 ) ),
+		notZeroExpr( maybeMoveBuild( expr_node2 ) ),
+		flag
+	);
 } // build_and_or
 
-Expression * build_unary_val( OperKinds op, ExpressionNode * expr_node ) {
-	list< Expression * > args;
+ast::Expr * build_unary_val( const CodeLocation & location,
+		OperKinds op,
+		ExpressionNode * expr_node ) {
+	std::vector<ast::ptr<ast::Expr>> args;
 	args.push_back( maybeMoveBuild( expr_node ) );
-	return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args );
+	return new ast::UntypedExpr( location,
+		new ast::NameExpr( location, OperName[ (int)op ] ),
+		std::move( args )
+	);
 } // build_unary_val
 
-Expression * build_binary_val( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 ) {
-	list< Expression * > args;
+ast::Expr * build_binary_val( const CodeLocation & location,
+		OperKinds op,
+		ExpressionNode * expr_node1,
+		ExpressionNode * expr_node2 ) {
+	std::vector<ast::ptr<ast::Expr>> args;
 	args.push_back( maybeMoveBuild( expr_node1 ) );
 	args.push_back( maybeMoveBuild( expr_node2 ) );
-	return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args );
+	return new ast::UntypedExpr( location,
+		new ast::NameExpr( location, OperName[ (int)op ] ),
+		std::move( args )
+	);
 } // build_binary_val
 
-Expression * build_binary_ptr( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 ) {
-	list< Expression * > args;
-	args.push_back( maybeMoveBuild( expr_node1 ) );
-	args.push_back( maybeMoveBuild( expr_node2 ) );
-	return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args );
+ast::Expr * build_binary_ptr( const CodeLocation & location,
+		OperKinds op,
+		ExpressionNode * expr_node1,
+		ExpressionNode * expr_node2 ) {
+	return build_binary_val( location, op, expr_node1, expr_node2 );
 } // build_binary_ptr
 
-Expression * build_cond( ExpressionNode * expr_node1, ExpressionNode * expr_node2, ExpressionNode * expr_node3 ) {
-	return new ConditionalExpr( notZeroExpr( maybeMoveBuild( expr_node1 ) ), maybeMoveBuild( expr_node2 ), maybeMoveBuild( expr_node3 ) );
+ast::Expr * build_cond( const CodeLocation & location,
+		ExpressionNode * expr_node1,
+		ExpressionNode * expr_node2,
+		ExpressionNode * expr_node3 ) {
+	return new ast::ConditionalExpr( location,
+		notZeroExpr( maybeMoveBuild( expr_node1 ) ),
+		maybeMoveBuild( expr_node2 ),
+		maybeMoveBuild( expr_node3 )
+	);
 } // build_cond
 
-Expression * build_tuple( ExpressionNode * expr_node ) {
-	list< Expression * > exprs;
+ast::Expr * build_tuple( const CodeLocation & location,
+		ExpressionNode * expr_node ) {
+	std::vector<ast::ptr<ast::Expr>> exprs;
 	buildMoveList( expr_node, exprs );
-	return new UntypedTupleExpr( exprs );;
+	return new ast::UntypedTupleExpr( location, std::move( exprs ) );
 } // build_tuple
 
-Expression * build_func( ExpressionNode * function, ExpressionNode * expr_node ) {
-	list< Expression * > args;
+ast::Expr * build_func( const CodeLocation & location,
+		ExpressionNode * function,
+		ExpressionNode * expr_node ) {
+	std::vector<ast::ptr<ast::Expr>> args;
 	buildMoveList( expr_node, args );
-	return new UntypedExpr( maybeMoveBuild( function ), args );
+	return new ast::UntypedExpr( location,
+		maybeMoveBuild( function ),
+		std::move( args )
+	);
 } // build_func
 
-Expression * build_compoundLiteral( DeclarationNode * decl_node, InitializerNode * kids ) {
-	Declaration * newDecl = maybeBuild( decl_node ); // compound literal type
-	if ( DeclarationWithType * newDeclWithType = dynamic_cast< DeclarationWithType * >( newDecl ) ) { // non-sue compound-literal type
-		return new CompoundLiteralExpr( newDeclWithType->get_type(), maybeMoveBuild( kids ) );
+ast::Expr * build_compoundLiteral( const CodeLocation & location,
+		DeclarationNode * decl_node,
+		InitializerNode * kids ) {
+	// compound literal type
+	ast::Decl * newDecl = maybeBuild( decl_node );
+	// non-sue compound-literal type
+	if ( ast::DeclWithType * newDeclWithType = dynamic_cast<ast::DeclWithType *>( newDecl ) ) {
+		return new ast::CompoundLiteralExpr( location,
+			newDeclWithType->get_type(),
+			maybeMoveBuild( kids ) );
 	// these types do not have associated type information
-	} else if ( StructDecl * newDeclStructDecl = dynamic_cast< StructDecl * >( newDecl )  ) {
-		if ( newDeclStructDecl->has_body() ) {
-			return new CompoundLiteralExpr( new StructInstType( Type::Qualifiers(), newDeclStructDecl ), maybeMoveBuild( kids ) );
+	} else if ( auto newDeclStructDecl = dynamic_cast<ast::StructDecl *>( newDecl ) ) {
+		if ( newDeclStructDecl->body ) {
+			return new ast::CompoundLiteralExpr( location,
+				new ast::StructInstType( newDeclStructDecl ),
+				maybeMoveBuild( kids ) );
 		} else {
-			return new CompoundLiteralExpr( new StructInstType( Type::Qualifiers(), newDeclStructDecl->get_name() ), maybeMoveBuild( kids ) );
-		} // if
-	} else if ( UnionDecl * newDeclUnionDecl = dynamic_cast< UnionDecl * >( newDecl )  ) {
-		if ( newDeclUnionDecl->has_body() ) {
-			return new CompoundLiteralExpr( new UnionInstType( Type::Qualifiers(), newDeclUnionDecl ), maybeMoveBuild( kids ) );
+			return new ast::CompoundLiteralExpr( location,
+				new ast::StructInstType( newDeclStructDecl->name ),
+				maybeMoveBuild( kids ) );
+		} // if
+	} else if ( auto newDeclUnionDecl = dynamic_cast<ast::UnionDecl *>( newDecl )  ) {
+		if ( newDeclUnionDecl->body ) {
+			return new ast::CompoundLiteralExpr( location,
+				new ast::UnionInstType( newDeclUnionDecl ),
+				maybeMoveBuild( kids ) );
 		} else {
-			return new CompoundLiteralExpr( new UnionInstType( Type::Qualifiers(), newDeclUnionDecl->get_name() ), maybeMoveBuild( kids ) );
-		} // if
-	} else if ( EnumDecl * newDeclEnumDecl = dynamic_cast< EnumDecl * >( newDecl )  ) {
-		if ( newDeclEnumDecl->has_body() ) {
-			return new CompoundLiteralExpr( new EnumInstType( Type::Qualifiers(), newDeclEnumDecl ), maybeMoveBuild( kids ) );
+			return new ast::CompoundLiteralExpr( location,
+				new ast::UnionInstType( newDeclUnionDecl->name ),
+				maybeMoveBuild( kids ) );
+		} // if
+	} else if ( auto newDeclEnumDecl = dynamic_cast<ast::EnumDecl *>( newDecl )  ) {
+		if ( newDeclEnumDecl->body ) {
+			return new ast::CompoundLiteralExpr( location,
+				new ast::EnumInstType( newDeclEnumDecl ),
+				maybeMoveBuild( kids ) );
 		} else {
-			return new CompoundLiteralExpr( new EnumInstType( Type::Qualifiers(), newDeclEnumDecl->get_name() ), maybeMoveBuild( kids ) );
+			return new ast::CompoundLiteralExpr( location,
+				new ast::EnumInstType( newDeclEnumDecl->name ),
+				maybeMoveBuild( kids ) );
 		} // if
 	} else {
Index: src/Parser/InitializerNode.cc
===================================================================
--- src/Parser/InitializerNode.cc	(revision 70056edafe6b115773f5da41e81a7b2adf5c08f5)
+++ src/Parser/InitializerNode.cc	(revision e02e13fc53b4a6d659a7753b2c843a4b7e203c0d)
@@ -9,7 +9,7 @@
 // Author           : Rodolfo G. Esteves
 // Created On       : Sat May 16 13:20:24 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Jul 28 23:27:20 2017
-// Update Count     : 26
+// Last Modified By : Andrew Beach
+// Last Modified On : Tue Apr  4 11:18:00 2023
+// Update Count     : 27
 //
 
@@ -20,9 +20,13 @@
 using namespace std;
 
+#include "AST/Expr.hpp"            // for Expr
+#include "AST/Init.hpp"            // for Designator, Init, ListInit, Sing...
 #include "Common/SemanticError.h"  // for SemanticError
 #include "Common/utility.h"        // for maybeBuild
 #include "ParseNode.h"             // for InitializerNode, ExpressionNode
-#include "SynTree/Expression.h"    // for Expression
-#include "SynTree/Initializer.h"   // for Initializer, ListInit, SingleInit
+
+static ast::ConstructFlag toConstructFlag( bool maybeConstructed ) {
+	return maybeConstructed ? ast::MaybeConstruct : ast::NoConstruct;
+}
 
 InitializerNode::InitializerNode( ExpressionNode * _expr, bool aggrp, ExpressionNode * des )
@@ -33,5 +37,5 @@
 	if ( kids )
 		set_last( nullptr );
-} // InitializerNode::InitializerNode
+} // InitializerNode::InitializerNode
 
 InitializerNode::InitializerNode( InitializerNode * init, bool aggrp, ExpressionNode * des )
@@ -85,23 +89,29 @@
 } // InitializerNode::printOneLine
 
-Initializer * InitializerNode::build() const {
+ast::Init * InitializerNode::build() const {
 	assertf( ! isDelete, "Should not build delete stmt InitializerNode" );
 	if ( aggregate ) {
 		// steal designators from children
-		std::list< Designation * > designlist;
+		std::vector<ast::ptr<ast::Designation>> designlist;
 		InitializerNode * child = next_init();
-		for ( ; child != nullptr; child = dynamic_cast< InitializerNode * >( child->get_next() ) ) {
-			std::list< Expression * > desList;
-			buildList< Expression, ExpressionNode >( child->designator, desList );
-			designlist.push_back( new Designation( desList ) );
+		for ( ; child != nullptr ; child = dynamic_cast< InitializerNode * >( child->get_next() ) ) {
+			std::deque<ast::ptr<ast::Expr>> desList;
+			buildList( child->designator, desList );
+			designlist.push_back(
+				new ast::Designation( location, std::move( desList ) ) );
 		} // for
-		std::list< Initializer * > initlist;
-		buildList< Initializer, InitializerNode >( next_init(), initlist );
-		return new ListInit( initlist, designlist, maybeConstructed );
-	} else {
-		if ( get_expression() ) {
-			assertf( get_expression()->expr, "The expression of initializer must have value" );
-			return new SingleInit( maybeBuild( get_expression() ), maybeConstructed );
-		} // if
+		std::vector<ast::ptr<ast::Init>> initlist;
+		buildList( next_init(), initlist );
+		return new ast::ListInit( location,
+			std::move( initlist ),
+			std::move( designlist ),
+			toConstructFlag( maybeConstructed )
+		);
+	} else if ( get_expression() ) {
+		assertf( get_expression()->expr, "The expression of initializer must have value" );
+		return new ast::SingleInit( location,
+			maybeBuild( get_expression() ),
+			toConstructFlag( maybeConstructed )
+		);
 	} // if
 	return nullptr;
Index: src/Parser/ParseNode.h
===================================================================
--- src/Parser/ParseNode.h	(revision 70056edafe6b115773f5da41e81a7b2adf5c08f5)
+++ src/Parser/ParseNode.h	(revision e02e13fc53b4a6d659a7753b2c843a4b7e203c0d)
@@ -9,7 +9,7 @@
 // Author           : Rodolfo G. Esteves
 // Created On       : Sat May 16 13:28:16 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Mar 29 08:40:27 2023
-// Update Count     : 948
+// Last Modified By : Andrew Beach
+// Last Modified On : Mon Apr  3 17:55:00 2023
+// Update Count     : 942
 //
 
@@ -24,15 +24,12 @@
 #include <string>                  // for string
 
+#include "AST/Expr.hpp"            // for Expr, NameExpr LogicalFlag
+#include "AST/Fwd.hpp"             // for ptr, Decl, DeclWithType,
+#include "AST/Stmt.hpp"            // for Stmt
 #include "Common/CodeLocation.h"   // for CodeLocation
 #include "Common/SemanticError.h"  // for SemanticError
 #include "Common/UniqueName.h"     // for UniqueName
 #include "Common/utility.h"        // for maybeClone
-#include "Parser/parserutility.h"  // for maybeBuild
-#include "SynTree/LinkageSpec.h"   // for Spec
-#include "SynTree/Declaration.h"   // for Aggregate
-#include "SynTree/Expression.h"    // for Expression, ConstantExpr (ptr only)
-#include "SynTree/Label.h"         // for Label
-#include "SynTree/Statement.h"     // for Statement, BranchStmt, BranchStmt:...
-#include "SynTree/Type.h"          // for Type, Type::FuncSpecifiers, Type::...
+#include "Parser/parserutility.h"  // for maybeBuild, maybeCopy
 
 class Attribute;
@@ -108,5 +105,5 @@
 	void printOneLine( std::ostream & ) const;
 
-	virtual Initializer * build() const;
+	virtual ast::Init * build() const;
   private:
 	ExpressionNode * expr;
@@ -122,7 +119,11 @@
 class ExpressionNode final : public ParseNode {
   public:
-	ExpressionNode( Expression * expr = nullptr ) : expr( expr ) {}
+	ExpressionNode( ast::Expr * expr = nullptr ) : expr( expr ) {}
 	virtual ~ExpressionNode() {}
-	virtual ExpressionNode * clone() const override { return expr ? static_cast<ExpressionNode*>((new ExpressionNode( expr->clone() ))->set_next( maybeClone( get_next() ) )) : nullptr; }
+	virtual ExpressionNode * clone() const override {
+		if ( nullptr == expr ) return nullptr;
+		return static_cast<ExpressionNode*>(
+			(new ExpressionNode( ast::shallowCopy( expr.get() ) ))->set_next( maybeCopy( get_next() ) ));
+	}
 
 	bool get_extension() const { return extension; }
@@ -137,6 +138,6 @@
 	bool isExpressionType() const {	return nullptr != dynamic_cast<T>(expr.get()); }
 
-	Expression * build() const {
-		Expression * node = const_cast<ExpressionNode *>(this)->expr.release();
+	ast::Expr * build() const {
+		ast::Expr * node = const_cast<ExpressionNode *>(this)->expr.release();
 		node->set_extension( this->get_extension() );
 		node->location = this->location;
@@ -144,5 +145,6 @@
 	}
 
-	std::unique_ptr<Expression> expr;					// public because of lifetime implications
+	// Public because of lifetime implications (what lifetime implications?)
+	std::unique_ptr<ast::Expr> expr;
   private:
 	bool extension = false;
@@ -164,36 +166,37 @@
 
 struct LabelNode {
-	std::list< Label > labels;
+	std::vector<ast::Label> labels;
 };
 
-Expression * build_constantInteger( std::string & str ); // these 4 routines modify the string
-Expression * build_constantFloat( std::string & str );
-Expression * build_constantChar( std::string & str );
-Expression * build_constantStr( std::string & str );
-Expression * build_field_name_FLOATING_FRACTIONconstant( const std::string & str );
-Expression * build_field_name_FLOATING_DECIMALconstant( const std::string & str );
-Expression * build_field_name_FLOATINGconstant( const std::string & str );
-Expression * build_field_name_fraction_constants( Expression * fieldName, ExpressionNode * fracts );
-
-NameExpr * build_varref( const std::string * name );
-QualifiedNameExpr * build_qualified_expr( const DeclarationNode * decl_node, const NameExpr * name );
-QualifiedNameExpr * build_qualified_expr( const EnumDecl * decl, const NameExpr * name );
-DimensionExpr * build_dimensionref( const std::string * name );
-
-Expression * build_cast( DeclarationNode * decl_node, ExpressionNode * expr_node );
-Expression * build_keyword_cast( AggregateDecl::Aggregate target, ExpressionNode * expr_node );
-Expression * build_virtual_cast( DeclarationNode * decl_node, ExpressionNode * expr_node );
-Expression * build_fieldSel( ExpressionNode * expr_node, Expression * member );
-Expression * build_pfieldSel( ExpressionNode * expr_node, Expression * member );
-Expression * build_offsetOf( DeclarationNode * decl_node, NameExpr * member );
-Expression * build_and( ExpressionNode * expr_node1, ExpressionNode * expr_node2 );
-Expression * build_and_or( ExpressionNode * expr_node1, ExpressionNode * expr_node2, bool kind );
-Expression * build_unary_val( OperKinds op, ExpressionNode * expr_node );
-Expression * build_binary_val( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 );
-Expression * build_binary_ptr( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 );
-Expression * build_cond( ExpressionNode * expr_node1, ExpressionNode * expr_node2, ExpressionNode * expr_node3 );
-Expression * build_tuple( ExpressionNode * expr_node = nullptr );
-Expression * build_func( ExpressionNode * function, ExpressionNode * expr_node );
-Expression * build_compoundLiteral( DeclarationNode * decl_node, InitializerNode * kids );
+// These 4 routines modify the string:
+ast::Expr * build_constantInteger( const CodeLocation &, std::string & );
+ast::Expr * build_constantFloat( const CodeLocation &, std::string & );
+ast::Expr * build_constantChar( const CodeLocation &, std::string & );
+ast::Expr * build_constantStr( const CodeLocation &, std::string & );
+ast::Expr * build_field_name_FLOATING_FRACTIONconstant( const CodeLocation &, const std::string & str );
+ast::Expr * build_field_name_FLOATING_DECIMALconstant( const CodeLocation &, const std::string & str );
+ast::Expr * build_field_name_FLOATINGconstant( const CodeLocation &, const std::string & str );
+ast::Expr * build_field_name_fraction_constants( const CodeLocation &, ast::Expr * fieldName, ExpressionNode * fracts );
+
+ast::NameExpr * build_varref( const CodeLocation &, const std::string * name );
+ast::QualifiedNameExpr * build_qualified_expr( const CodeLocation &, const DeclarationNode * decl_node, const ast::NameExpr * name );
+ast::QualifiedNameExpr * build_qualified_expr( const CodeLocation &, const ast::EnumDecl * decl, const ast::NameExpr * name );
+ast::DimensionExpr * build_dimensionref( const CodeLocation &, const std::string * name );
+
+ast::Expr * build_cast( const CodeLocation &, DeclarationNode * decl_node, ExpressionNode * expr_node );
+ast::Expr * build_keyword_cast( const CodeLocation &, ast::AggregateDecl::Aggregate target, ExpressionNode * expr_node );
+ast::Expr * build_virtual_cast( const CodeLocation &, DeclarationNode * decl_node, ExpressionNode * expr_node );
+ast::Expr * build_fieldSel( const CodeLocation &, ExpressionNode * expr_node, ast::Expr * member );
+ast::Expr * build_pfieldSel( const CodeLocation &, ExpressionNode * expr_node, ast::Expr * member );
+ast::Expr * build_offsetOf( const CodeLocation &, DeclarationNode * decl_node, ast::NameExpr * member );
+ast::Expr * build_and( const CodeLocation &, ExpressionNode * expr_node1, ExpressionNode * expr_node2 );
+ast::Expr * build_and_or( const CodeLocation &, ExpressionNode * expr_node1, ExpressionNode * expr_node2, ast::LogicalFlag flag );
+ast::Expr * build_unary_val( const CodeLocation &, OperKinds op, ExpressionNode * expr_node );
+ast::Expr * build_binary_val( const CodeLocation &, OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 );
+ast::Expr * build_binary_ptr( const CodeLocation &, OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 );
+ast::Expr * build_cond( const CodeLocation &, ExpressionNode * expr_node1, ExpressionNode * expr_node2, ExpressionNode * expr_node3 );
+ast::Expr * build_tuple( const CodeLocation &, ExpressionNode * expr_node = nullptr );
+ast::Expr * build_func( const CodeLocation &, ExpressionNode * function, ExpressionNode * expr_node );
+ast::Expr * build_compoundLiteral( const CodeLocation &, DeclarationNode * decl_node, InitializerNode * kids );
 
 //##############################################################################
@@ -219,7 +222,7 @@
 	static const char * builtinTypeNames[];
 
-	static DeclarationNode * newStorageClass( Type::StorageClasses );
-	static DeclarationNode * newFuncSpecifier( Type::FuncSpecifiers );
-	static DeclarationNode * newTypeQualifier( Type::Qualifiers );
+	static DeclarationNode * newStorageClass( ast::Storage::Classes );
+	static DeclarationNode * newFuncSpecifier( ast::Function::Specs );
+	static DeclarationNode * newTypeQualifier( ast::CV::Qualifiers );
 	static DeclarationNode * newBasicType( BasicType );
 	static DeclarationNode * newComplexType( ComplexType );
@@ -232,5 +235,5 @@
 	static DeclarationNode * newQualifiedType( DeclarationNode *, DeclarationNode * );
 	static DeclarationNode * newFunction( const std::string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body );
-	static DeclarationNode * newAggregate( AggregateDecl::Aggregate kind, const std::string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body );
+	static DeclarationNode * newAggregate( ast::AggregateDecl::Aggregate kind, const std::string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body );
 	static DeclarationNode * newEnum( const std::string * name, DeclarationNode * constants, bool body, bool typed, DeclarationNode * base = nullptr, EnumHiding hiding = EnumHiding::Visible );
 	static DeclarationNode * newEnumConstant( const std::string * name, ExpressionNode * constant );
@@ -239,5 +242,5 @@
 	static DeclarationNode * newName( const std::string * );
 	static DeclarationNode * newFromTypeGen( const std::string *, ExpressionNode * params );
-	static DeclarationNode * newTypeParam( TypeDecl::Kind, const std::string * );
+	static DeclarationNode * newTypeParam( ast::TypeDecl::Kind, const std::string * );
 	static DeclarationNode * newTrait( const std::string * name, DeclarationNode * params, DeclarationNode * asserts );
 	static DeclarationNode * newTraitUse( const std::string * name, ExpressionNode * params );
@@ -253,5 +256,5 @@
 	static DeclarationNode * newDirectiveStmt( StatementNode * stmt ); // gcc external directive statement
 	static DeclarationNode * newAsmStmt( StatementNode * stmt ); // gcc external asm statement
-	static DeclarationNode * newStaticAssert( ExpressionNode * condition, Expression * message );
+	static DeclarationNode * newStaticAssert( ExpressionNode * condition, ast::Expr * message );
 
 	DeclarationNode();
@@ -294,8 +297,8 @@
 	virtual void printList( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const override;
 
-	Declaration * build() const;
-	Type * buildType() const;
-
-	LinkageSpec::Spec get_linkage() const { return linkage; }
+	ast::Decl * build() const;
+	ast::Type * buildType() const;
+
+	ast::Linkage::Spec get_linkage() const { return linkage; }
 	DeclarationNode * extractAggregate() const;
 	bool has_enumeratorValue() const { return (bool)enumeratorValue; }
@@ -312,5 +315,5 @@
 	struct Variable_t {
 //		const std::string * name;
-		TypeDecl::Kind tyClass;
+		ast::TypeDecl::Kind tyClass;
 		DeclarationNode * assertions;
 		DeclarationNode * initializer;
@@ -320,5 +323,5 @@
 	struct StaticAssert_t {
 		ExpressionNode * condition;
-		Expression * message;
+		ast::Expr * message;
 	};
 	StaticAssert_t assert;
@@ -330,13 +333,13 @@
 	bool inLine = false;
 	bool enumInLine = false;
-	Type::FuncSpecifiers funcSpecs;
-	Type::StorageClasses storageClasses;
+	ast::Function::Specs funcSpecs;
+	ast::Storage::Classes storageClasses;
 
 	ExpressionNode * bitfieldWidth = nullptr;
 	std::unique_ptr<ExpressionNode> enumeratorValue;
 	bool hasEllipsis = false;
-	LinkageSpec::Spec linkage;
-	Expression * asmName = nullptr;
-	std::list< Attribute * > attributes;
+	ast::Linkage::Spec linkage;
+	ast::Expr * asmName = nullptr;
+	std::vector<ast::ptr<ast::Attribute>> attributes;
 	InitializerNode * initializer = nullptr;
 	bool extension = false;
@@ -348,8 +351,8 @@
 }; // DeclarationNode
 
-Type * buildType( TypeData * type );
-
-static inline Type * maybeMoveBuildType( const DeclarationNode * orig ) {
-	Type * ret = orig ? orig->buildType() : nullptr;
+ast::Type * buildType( TypeData * type );
+
+static inline ast::Type * maybeMoveBuildType( const DeclarationNode * orig ) {
+	ast::Type * ret = orig ? orig->buildType() : nullptr;
 	delete orig;
 	return ret;
@@ -359,14 +362,24 @@
 
 struct StatementNode final : public ParseNode {
-	StatementNode() { stmt = nullptr; }
-	StatementNode( Statement * stmt ) : stmt( stmt ) {}
+	StatementNode() :
+		stmt( nullptr ), clause( nullptr ) {}
+	StatementNode( ast::Stmt * stmt ) :
+		stmt( stmt ), clause( nullptr ) {}
+	StatementNode( ast::StmtClause * clause ) :
+		stmt( nullptr ), clause( clause ) {}
 	StatementNode( DeclarationNode * decl );
 	virtual ~StatementNode() {}
 
 	virtual StatementNode * clone() const final { assert( false ); return nullptr; }
-	Statement * build() const { return const_cast<StatementNode *>(this)->stmt.release(); }
-
-	virtual StatementNode * add_label( const std::string * name, DeclarationNode * attr = nullptr ) {
-		stmt->get_labels().emplace_back( * name, nullptr, attr ? std::move( attr->attributes ) : std::list< Attribute * > {} );
+	ast::Stmt * build() const { return const_cast<StatementNode *>(this)->stmt.release(); }
+
+	virtual StatementNode * add_label(
+			const CodeLocation & location,
+			const std::string * name,
+			DeclarationNode * attr = nullptr ) {
+		stmt->labels.emplace_back( location,
+			*name,
+			attr ? std::move( attr->attributes )
+				: std::vector<ast::ptr<ast::Attribute>>{} );
 		delete attr;
 		delete name;
@@ -380,8 +393,9 @@
 	}
 
-	std::unique_ptr<Statement> stmt;
+	std::unique_ptr<ast::Stmt> stmt;
+	std::unique_ptr<ast::StmtClause> clause;
 }; // StatementNode
 
-Statement * build_expr( ExpressionNode * ctl );
+ast::Stmt * build_expr( CodeLocation const &, ExpressionNode * ctl );
 
 struct CondCtl {
@@ -402,48 +416,48 @@
 };
 
-Expression * build_if_control( CondCtl * ctl, std::list< Statement * > & init );
-Statement * build_if( CondCtl * ctl, StatementNode * then, StatementNode * else_ );
-Statement * build_switch( bool isSwitch, ExpressionNode * ctl, StatementNode * stmt );
-Statement * build_case( ExpressionNode * ctl );
-Statement * build_default();
-Statement * build_while( CondCtl * ctl, StatementNode * stmt, StatementNode * else_ = nullptr );
-Statement * build_do_while( ExpressionNode * ctl, StatementNode * stmt, StatementNode * else_ = nullptr );
-Statement * build_for( ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ = nullptr );
-Statement * build_branch( BranchStmt::Type kind );
-Statement * build_branch( std::string * identifier, BranchStmt::Type kind );
-Statement * build_computedgoto( ExpressionNode * ctl );
-Statement * build_return( ExpressionNode * ctl );
-Statement * build_throw( ExpressionNode * ctl );
-Statement * build_resume( ExpressionNode * ctl );
-Statement * build_resume_at( ExpressionNode * ctl , ExpressionNode * target );
-Statement * build_try( StatementNode * try_, StatementNode * catch_, StatementNode * finally_ );
-Statement * build_catch( CatchStmt::Kind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body );
-Statement * build_finally( StatementNode * stmt );
-Statement * build_compound( StatementNode * first );
-StatementNode * maybe_build_compound( StatementNode * first );
-Statement * build_asm( bool voltile, Expression * instruction, ExpressionNode * output = nullptr, ExpressionNode * input = nullptr, ExpressionNode * clobber = nullptr, LabelNode * gotolabels = nullptr );
-Statement * build_directive( std::string * directive );
-SuspendStmt * build_suspend( StatementNode *, SuspendStmt::Type = SuspendStmt::None);
-WaitForStmt * build_waitfor( WaitForStmt * existing, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt );
-WaitForStmt * build_waitfor_else( WaitForStmt * existing, ExpressionNode * when, StatementNode * stmt );
-WaitForStmt * build_waitfor_timeout( WaitForStmt * existing, ExpressionNode * when, ExpressionNode * timeout, StatementNode * stmt );
-Statement * build_with( ExpressionNode * exprs, StatementNode * stmt );
-Statement * build_mutex( ExpressionNode * exprs, StatementNode * stmt );
-
-//##############################################################################
-
-template< typename SynTreeType, typename NodeType, template< typename, typename...> class Container, typename... Args >
-void buildList( const NodeType * firstNode, Container< SynTreeType *, Args... > & outputList ) {
+ast::Stmt * build_if( const CodeLocation &, CondCtl * ctl, StatementNode * then, StatementNode * else_ );
+ast::Stmt * build_switch( const CodeLocation &, bool isSwitch, ExpressionNode * ctl, StatementNode * stmt );
+ast::CaseClause * build_case( ExpressionNode * ctl );
+ast::CaseClause * build_default( const CodeLocation & );
+ast::Stmt * build_while( const CodeLocation &, CondCtl * ctl, StatementNode * stmt, StatementNode * else_ = nullptr );
+ast::Stmt * build_do_while( const CodeLocation &, ExpressionNode * ctl, StatementNode * stmt, StatementNode * else_ = nullptr );
+ast::Stmt * build_for( const CodeLocation &, ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ = nullptr );
+ast::Stmt * build_branch( const CodeLocation &, ast::BranchStmt::Kind kind );
+ast::Stmt * build_branch( const CodeLocation &, std::string * identifier, ast::BranchStmt::Kind kind );
+ast::Stmt * build_computedgoto( ExpressionNode * ctl );
+ast::Stmt * build_return( const CodeLocation &, ExpressionNode * ctl );
+ast::Stmt * build_throw( const CodeLocation &, ExpressionNode * ctl );
+ast::Stmt * build_resume( const CodeLocation &, ExpressionNode * ctl );
+ast::Stmt * build_resume_at( ExpressionNode * ctl , ExpressionNode * target );
+ast::Stmt * build_try( const CodeLocation &, StatementNode * try_, StatementNode * catch_, StatementNode * finally_ );
+ast::CatchClause * build_catch( const CodeLocation &, ast::ExceptionKind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body );
+ast::FinallyClause * build_finally( const CodeLocation &, StatementNode * stmt );
+ast::Stmt * build_compound( const CodeLocation &, StatementNode * first );
+StatementNode * maybe_build_compound( const CodeLocation &, StatementNode * first );
+ast::Stmt * build_asm( const CodeLocation &, bool voltile, ast::Expr * instruction, ExpressionNode * output = nullptr, ExpressionNode * input = nullptr, ExpressionNode * clobber = nullptr, LabelNode * gotolabels = nullptr );
+ast::Stmt * build_directive( const CodeLocation &, std::string * directive );
+ast::SuspendStmt * build_suspend( const CodeLocation &, StatementNode *, ast::SuspendStmt::Type );
+ast::WaitForStmt * build_waitfor( const CodeLocation &, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt );
+ast::WaitForStmt * build_waitfor_else( const CodeLocation &, ast::WaitForStmt * existing, ExpressionNode * when, StatementNode * stmt );
+ast::WaitForStmt * build_waitfor_timeout( const CodeLocation &, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * timeout, StatementNode * stmt );
+ast::Stmt * build_with( const CodeLocation &, ExpressionNode * exprs, StatementNode * stmt );
+ast::Stmt * build_mutex( const CodeLocation &, ExpressionNode * exprs, StatementNode * stmt );
+
+//##############################################################################
+
+template<typename AstType, typename NodeType,
+	template<typename, typename...> class Container, typename... Args>
+void buildList( const NodeType * firstNode,
+		Container<ast::ptr<AstType>, Args...> & output ) {
 	SemanticErrorException errors;
-	std::back_insert_iterator< Container< SynTreeType *, Args... > > out( outputList );
+	std::back_insert_iterator<Container<ast::ptr<AstType>, Args...>> out( output );
 	const NodeType * cur = firstNode;
 
 	while ( cur ) {
 		try {
-			SynTreeType * result = dynamic_cast< SynTreeType * >( maybeBuild( cur ) );
-			if ( result ) {
-				result->location = cur->location;
-				* out++ = result;
+			if ( auto result = dynamic_cast<AstType *>( maybeBuild( cur ) ) ) {
+				*out++ = result;
 			} else {
+				assertf(false, __PRETTY_FUNCTION__ );
 				SemanticError( cur->location, "type specifier declaration in forall clause is currently unimplemented." );
 			} // if
@@ -451,7 +465,8 @@
 			errors.append( e );
 		} // try
-		const ParseNode * temp = (cur->get_next());
-		cur = dynamic_cast< const NodeType * >( temp );	// should not return nullptr
-		if ( ! cur && temp ) {							// non-homogeneous nodes ?
+		const ParseNode * temp = cur->get_next();
+		// Should not return nullptr, then it is non-homogeneous:
+		cur = dynamic_cast<const NodeType *>( temp );
+		if ( !cur && temp ) {
 			SemanticError( temp->location, "internal error, non-homogeneous nodes founds in buildList processing." );
 		} // if
@@ -463,11 +478,13 @@
 
 // in DeclarationNode.cc
-void buildList( const DeclarationNode * firstNode, std::list< Declaration * > & outputList );
-void buildList( const DeclarationNode * firstNode, std::list< DeclarationWithType * > & outputList );
-void buildTypeList( const DeclarationNode * firstNode, std::list< Type * > & outputList );
-
-template< typename SynTreeType, typename NodeType >
-void buildMoveList( const NodeType * firstNode, std::list< SynTreeType * > & outputList ) {
-	buildList( firstNode, outputList );
+void buildList( const DeclarationNode * firstNode, std::vector<ast::ptr<ast::Decl>> & outputList );
+void buildList( const DeclarationNode * firstNode, std::vector<ast::ptr<ast::DeclWithType>> & outputList );
+void buildTypeList( const DeclarationNode * firstNode, std::vector<ast::ptr<ast::Type>> & outputList );
+
+template<typename AstType, typename NodeType,
+	template<typename, typename...> class Container, typename... Args>
+void buildMoveList( const NodeType * firstNode,
+		Container<ast::ptr<AstType>, Args...> & output ) {
+	buildList<AstType, NodeType, Container, Args...>( firstNode, output );
 	delete firstNode;
 }
Index: src/Parser/ParserTypes.h
===================================================================
--- src/Parser/ParserTypes.h	(revision 70056edafe6b115773f5da41e81a7b2adf5c08f5)
+++ src/Parser/ParserTypes.h	(revision e02e13fc53b4a6d659a7753b2c843a4b7e203c0d)
@@ -4,7 +4,7 @@
 // The contents of this file are covered under the licence agreement in the
 // file "LICENCE" distributed with Cforall.
-// 
-// parser.hh -- 
-// 
+//
+// parser.hh --
+//
 // Author           : Peter A. Buhr
 // Created On       : Sat Sep 22 08:58:10 2001
Index: src/Parser/RunParser.cpp
===================================================================
--- src/Parser/RunParser.cpp	(revision 70056edafe6b115773f5da41e81a7b2adf5c08f5)
+++ src/Parser/RunParser.cpp	(revision e02e13fc53b4a6d659a7753b2c843a4b7e203c0d)
@@ -10,6 +10,6 @@
 // Created On       : Mon Dec 19 11:00:00 2022
 // Last Modified By : Andrew Beach
-// Last Modified On : Thr Feb 16 10:08:00 2023
-// Update Count     : 2
+// Last Modified On : Mon Mar  6  9:42:00 2023
+// Update Count     : 3
 //
 
@@ -46,16 +46,13 @@
 
 ast::TranslationUnit buildUnit(void) {
-	std::list<Declaration *> translationUnit;
-	buildList( parseTree, translationUnit );
-
+	std::vector<ast::ptr<ast::Decl>> decls;
+	buildList( parseTree, decls );
 	delete parseTree;
 	parseTree = nullptr;
 
-	// When the parse/buildList code is translated to the new ast, these
-	// fill passes (and the one after 'Hoist Type Decls') should be redundent
-	// because the code locations should already be filled.
-	CodeTools::fillLocations( translationUnit );
-	ast::TranslationUnit transUnit = convert( std::move( translationUnit ) );
-	forceFillCodeLocations( transUnit );
+	ast::TranslationUnit transUnit;
+	for ( auto decl : decls ) {
+		transUnit.decls.emplace_back( std::move( decl ) );
+	}
 	return transUnit;
 }
Index: src/Parser/StatementNode.cc
===================================================================
--- src/Parser/StatementNode.cc	(revision 70056edafe6b115773f5da41e81a7b2adf5c08f5)
+++ src/Parser/StatementNode.cc	(revision e02e13fc53b4a6d659a7753b2c843a4b7e203c0d)
@@ -10,21 +10,18 @@
 // Author           : Rodolfo G. Esteves
 // Created On       : Sat May 16 14:59:41 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Mar 29 08:51:23 2023
-// Update Count     : 454
+// Last Modified By : Andrew Beach
+// Last Modified On : Tue Apr  4 11:40:00 2023
+// Update Count     : 427
 //
 
 #include <cassert>                 // for assert, strict_dynamic_cast, assertf
-#include <list>                    // for list
 #include <memory>                  // for unique_ptr
 #include <string>                  // for string
 
+#include "AST/Label.hpp"           // for Label
+#include "AST/Stmt.hpp"            // for Stmt, AsmStmt, BranchStmt, CaseCla...
 #include "Common/SemanticError.h"  // for SemanticError
 #include "Common/utility.h"        // for maybeMoveBuild, maybeBuild
 #include "ParseNode.h"             // for StatementNode, ExpressionNode, bui...
-#include "SynTree/Expression.h"    // for Expression, ConstantExpr
-#include "SynTree/Label.h"         // for Label, noLabels
-#include "SynTree/Declaration.h"
-#include "SynTree/Statement.h"     // for Statement, BranchStmt, CaseStmt
 #include "parserutility.h"         // for notZeroExpr
 
@@ -32,5 +29,4 @@
 
 using namespace std;
-
 
 StatementNode::StatementNode( DeclarationNode * decl ) {
@@ -38,5 +34,6 @@
 	DeclarationNode * agg = decl->extractAggregate();
 	if ( agg ) {
-		StatementNode * nextStmt = new StatementNode( new DeclStmt( maybeBuild( decl ) ) );
+		StatementNode * nextStmt = new StatementNode(
+			new ast::DeclStmt( decl->location, maybeBuild( decl ) ) );
 		set_next( nextStmt );
 		if ( decl->get_next() ) {
@@ -51,5 +48,7 @@
 		agg = decl;
 	} // if
-	stmt.reset( new DeclStmt( maybeMoveBuild( agg ) ) );
+	// Local copy to avoid accessing the pointer after it is moved from.
+	CodeLocation declLocation = agg->location;
+	stmt.reset( new ast::DeclStmt( declLocation, maybeMoveBuild( agg ) ) );
 } // StatementNode::StatementNode
 
@@ -59,40 +58,49 @@
 	for ( StatementNode * curr = prev; curr != nullptr; curr = (StatementNode *)curr->get_next() ) {
 		StatementNode * node = strict_dynamic_cast< StatementNode * >(curr);
-		assert( dynamic_cast< CaseStmt * >(node->stmt.get()) );
+		assert( nullptr == node->stmt.get() );
+		assert( dynamic_cast<ast::CaseClause *>( node->clause.get() ) );
 		prev = curr;
 	} // for
 	// convert from StatementNode list to Statement list
 	StatementNode * node = dynamic_cast< StatementNode * >(prev);
-	list< Statement * > stmts;
+	std::vector<ast::ptr<ast::Stmt>> stmts;
 	buildMoveList( stmt, stmts );
 	// splice any new Statements to end of current Statements
-	CaseStmt * caseStmt = dynamic_cast< CaseStmt * >(node->stmt.get());
-	caseStmt->get_statements().splice( caseStmt->get_statements().end(), stmts );
+	auto caseStmt = strict_dynamic_cast<ast::CaseClause *>( node->clause.get() );
+	for ( auto const & newStmt : stmts ) {
+		caseStmt->stmts.emplace_back( newStmt );
+	}
+	stmts.clear();
 	return this;
 } // StatementNode::append_last_case
 
-Statement * build_expr( ExpressionNode * ctl ) {
-	Expression * e = maybeMoveBuild( ctl );
-
-	if ( e ) return new ExprStmt( e );
-	else return new NullStmt();
+ast::Stmt * build_expr( CodeLocation const & location, ExpressionNode * ctl ) {
+	if ( ast::Expr * e = maybeMoveBuild( ctl ) ) {
+		return new ast::ExprStmt( location, e );
+	} else {
+		return new ast::NullStmt( location );
+	}
 } // build_expr
 
-Expression * build_if_control( CondCtl * ctl, list< Statement * > & init ) {
-	if ( ctl->init != 0 ) {
-		buildMoveList( ctl->init, init );
-	} // if
-
-	Expression * cond = nullptr;
+static ast::Expr * build_if_control( CondCtl * ctl,
+		std::vector<ast::ptr<ast::Stmt>> & inits ) {
+	assert( inits.empty() );
+	if ( nullptr != ctl->init ) {
+		buildMoveList( ctl->init, inits );
+	} // if
+
+	ast::Expr * cond = nullptr;
 	if ( ctl->condition ) {
 		// compare the provided condition against 0
 		cond = notZeroExpr( maybeMoveBuild( ctl->condition ) );
 	} else {
-		for ( Statement * stmt : init ) {
+		for ( ast::ptr<ast::Stmt> & stmt : inits ) {
 			// build the && of all of the declared variables compared against 0
-			DeclStmt * declStmt = strict_dynamic_cast< DeclStmt * >( stmt );
-			DeclarationWithType * dwt = strict_dynamic_cast< DeclarationWithType * >( declStmt->decl );
-			Expression * nze = notZeroExpr( new VariableExpr( dwt ) );
-			cond = cond ? new LogicalExpr( cond, nze, true ) : nze;
+			//auto declStmt = strict_dynamic_cast<ast::DeclStmt *>( stmt );
+			auto declStmt = stmt.strict_as<ast::DeclStmt>();
+			//ast::DeclWithType * dwt = strict_dynamic_cast<ast::DeclWithType *>( declStmt->decl );
+			auto dwt = declStmt->decl.strict_as<ast::DeclWithType>();
+			ast::Expr * nze = notZeroExpr( new ast::VariableExpr( dwt->location, dwt ) );
+			cond = cond ? new ast::LogicalExpr( dwt->location, cond, nze, ast::AndExpr ) : nze;
 		}
 	}
@@ -101,131 +109,216 @@
 } // build_if_control
 
-Statement * build_if( CondCtl * ctl, StatementNode * then, StatementNode * else_ ) {
-	list< Statement * > astinit;						// maybe empty
-	Expression * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set
-
-	Statement * astthen, * astelse = nullptr;
-	list< Statement * > aststmt;
-	buildMoveList< Statement, StatementNode >( then, aststmt );
+ast::Stmt * build_if( const CodeLocation & location, CondCtl * ctl, StatementNode * then, StatementNode * else_ ) {
+	std::vector<ast::ptr<ast::Stmt>> astinit;						// maybe empty
+	ast::Expr * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set
+
+	std::vector<ast::ptr<ast::Stmt>> aststmt;
+	buildMoveList( then, aststmt );
 	assert( aststmt.size() == 1 );
-	astthen = aststmt.front();
-
+	ast::Stmt const * astthen = aststmt.front().release();
+
+	ast::Stmt const * astelse = nullptr;
 	if ( else_ ) {
-		list< Statement * > aststmt;
-		buildMoveList< Statement, StatementNode >( else_, aststmt );
+		std::vector<ast::ptr<ast::Stmt>> aststmt;
+		buildMoveList( else_, aststmt );
 		assert( aststmt.size() == 1 );
-		astelse = aststmt.front();
-	} // if
-
-	return new IfStmt( astcond, astthen, astelse, astinit );
+		astelse = aststmt.front().release();
+	} // if
+
+	return new ast::IfStmt( location, astcond, astthen, astelse,
+		std::move( astinit )
+	);
 } // build_if
 
-Statement * build_switch( bool isSwitch, ExpressionNode * ctl, StatementNode * stmt ) {
-	list< Statement * > aststmt;
-	buildMoveList< Statement, StatementNode >( stmt, aststmt );
-	if ( ! isSwitch ) {									// choose statement
-		for ( Statement * stmt : aststmt ) {
-			CaseStmt * caseStmt = strict_dynamic_cast< CaseStmt * >( stmt );
-			if ( ! caseStmt->stmts.empty() ) {			// code after "case" => end of case list
-				CompoundStmt * block = strict_dynamic_cast< CompoundStmt * >( caseStmt->stmts.front() );
-				block->kids.push_back( new BranchStmt( "", BranchStmt::Break ) );
+// Temporary work around. Split StmtClause off from StatementNode.
+template<typename clause_t>
+static void buildMoveClauseList( StatementNode * firstNode,
+		std::vector<ast::ptr<clause_t>> & output ) {
+	SemanticErrorException errors;
+	std::back_insert_iterator<std::vector<ast::ptr<clause_t>>>
+		out( output );
+	StatementNode * cur = firstNode;
+
+	while ( cur ) {
+		try {
+			auto clause = cur->clause.release();
+			if ( auto result = dynamic_cast<clause_t *>( clause ) ) {
+				*out++ = result;
+			} else {
+				assertf(false, __PRETTY_FUNCTION__ );
+				SemanticError( cur->location, "type specifier declaration in forall clause is currently unimplemented." );
+			} // if
+		} catch( SemanticErrorException & e ) {
+			errors.append( e );
+		} // try
+		ParseNode * temp = cur->get_next();
+		// Should not return nullptr, then it is non-homogeneous:
+		cur = dynamic_cast<StatementNode *>( temp );
+		if ( !cur && temp ) {
+			SemanticError( temp->location, "internal error, non-homogeneous nodes founds in buildList processing." );
+		} // if
+	} // while
+	if ( ! errors.isEmpty() ) {
+		throw errors;
+	} // if
+	// Usually in the wrapper.
+	delete firstNode;
+}
+
+ast::Stmt * build_switch( const CodeLocation & location, bool isSwitch, ExpressionNode * ctl, StatementNode * stmt ) {
+	std::vector<ast::ptr<ast::CaseClause>> aststmt;
+	buildMoveClauseList( stmt, aststmt );
+	// If it is not a switch it is a choose statement.
+	if ( ! isSwitch ) {
+		for ( ast::ptr<ast::CaseClause> & stmt : aststmt ) {
+			// Code after "case" is the end of case list.
+			if ( !stmt->stmts.empty() ) {
+				auto mutStmt = ast::mutate( stmt.get() );
+				// I believe the stmts are actually always one block.
+				auto stmts = mutStmt->stmts.front().get_and_mutate();
+				auto block = strict_dynamic_cast<ast::CompoundStmt *>( stmts );
+				block->kids.push_back( new ast::BranchStmt( block->location,
+					ast::BranchStmt::Break,
+					ast::Label( block->location ) ) );
+				stmt = mutStmt;
 			} // if
 		} // for
 	} // if
 	// aststmt.size() == 0 for switch (...) {}, i.e., no declaration or statements
-	return new SwitchStmt( maybeMoveBuild( ctl ), aststmt );
+	return new ast::SwitchStmt( location,
+		maybeMoveBuild( ctl ), std::move( aststmt ) );
 } // build_switch
 
-Statement * build_case( ExpressionNode * ctl ) {
-	return new CaseStmt( maybeMoveBuild( ctl ), {} ); // stmt starts empty and then added to
+ast::CaseClause * build_case( ExpressionNode * ctl ) {
+	// stmt starts empty and then added to
+	auto expr = maybeMoveBuild( ctl );
+	return new ast::CaseClause( expr->location, expr, {} );
 } // build_case
 
-Statement * build_default() {
-	return new CaseStmt( nullptr, {}, true );			// stmt starts empty and then added to
+ast::CaseClause * build_default( const CodeLocation & location ) {
+	// stmt starts empty and then added to
+	return new ast::CaseClause( location, nullptr, {} );
 } // build_default
 
-Statement * build_while( CondCtl * ctl, StatementNode * stmt, StatementNode * else_ ) {
-	list< Statement * > astinit;						// maybe empty
-	Expression * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set
-
-	list< Statement * > aststmt;						// loop body, compound created if empty
-	buildMoveList< Statement, StatementNode >( stmt, aststmt );
+ast::Stmt * build_while( const CodeLocation & location, CondCtl * ctl, StatementNode * stmt, StatementNode * else_ ) {
+	std::vector<ast::ptr<ast::Stmt>> astinit;						// maybe empty
+	ast::Expr * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set
+
+	std::vector<ast::ptr<ast::Stmt>> aststmt;						// loop body, compound created if empty
+	buildMoveList( stmt, aststmt );
 	assert( aststmt.size() == 1 );
 
-	list< Statement * > astelse;						// else clause, maybe empty
-	buildMoveList< Statement, StatementNode >( else_, astelse );
-
-	return new WhileDoStmt( astcond, aststmt.front(), astelse.front(), astinit, false );
+	std::vector<ast::ptr<ast::Stmt>> astelse;						// else clause, maybe empty
+	buildMoveList( else_, astelse );
+	assert( astelse.size() <= 1 );
+
+	return new ast::WhileDoStmt( location,
+		astcond,
+		aststmt.front(),
+		astelse.empty() ? nullptr : astelse.front().release(),
+		std::move( astinit ),
+		false
+	);
 } // build_while
 
-Statement * build_do_while( ExpressionNode * ctl, StatementNode * stmt, StatementNode * else_ ) {
-	list< Statement * > aststmt;						// loop body, compound created if empty
-	buildMoveList< Statement, StatementNode >( stmt, aststmt );
+ast::Stmt * build_do_while( const CodeLocation & location, ExpressionNode * ctl, StatementNode * stmt, StatementNode * else_ ) {
+	std::vector<ast::ptr<ast::Stmt>> aststmt;						// loop body, compound created if empty
+	buildMoveList( stmt, aststmt );
 	assert( aststmt.size() == 1 );						// compound created if empty
 
-	list< Statement * > astelse;						// else clause, maybe empty
-	buildMoveList< Statement, StatementNode >( else_, astelse );
+	std::vector<ast::ptr<ast::Stmt>> astelse;						// else clause, maybe empty
+	buildMoveList( else_, astelse );
+	assert( astelse.size() <= 1 );
 
 	// do-while cannot have declarations in the contitional, so init is always empty
-	return new WhileDoStmt( notZeroExpr( maybeMoveBuild( ctl ) ), aststmt.front(), astelse.front(), {}, true );
+	return new ast::WhileDoStmt( location,
+		notZeroExpr( maybeMoveBuild( ctl ) ),
+		aststmt.front(),
+		astelse.empty() ? nullptr : astelse.front().release(),
+		{},
+		true
+	);
 } // build_do_while
 
-Statement * build_for( ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ ) {
-	list< Statement * > astinit;						// maybe empty
+ast::Stmt * build_for( const CodeLocation & location, ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ ) {
+	std::vector<ast::ptr<ast::Stmt>> astinit;						// maybe empty
 	buildMoveList( forctl->init, astinit );
 
-	Expression * astcond = nullptr;						// maybe empty
+	ast::Expr * astcond = nullptr;						// maybe empty
 	astcond = notZeroExpr( maybeMoveBuild( forctl->condition ) );
 
-	Expression * astincr = nullptr;						// maybe empty
+	ast::Expr * astincr = nullptr;						// maybe empty
 	astincr = maybeMoveBuild( forctl->change );
 	delete forctl;
 
-	list< Statement * > aststmt;						// loop body, compound created if empty
-	buildMoveList< Statement, StatementNode >( stmt, aststmt );
+	std::vector<ast::ptr<ast::Stmt>> aststmt;						// loop body, compound created if empty
+	buildMoveList( stmt, aststmt );
 	assert( aststmt.size() == 1 );
 
-	list< Statement * > astelse;						// else clause, maybe empty
-	buildMoveList< Statement, StatementNode >( else_, astelse );
-
-	return new ForStmt( astinit, astcond, astincr, aststmt.front(), astelse.front() );
+	std::vector<ast::ptr<ast::Stmt>> astelse;						// else clause, maybe empty
+	buildMoveList( else_, astelse );
+	assert( astelse.size() <= 1 );
+
+	return new ast::ForStmt( location,
+		std::move( astinit ),
+		astcond,
+		astincr,
+		aststmt.front(),
+		astelse.empty() ? nullptr : astelse.front().release()
+	);
 } // build_for
 
-Statement * build_branch( BranchStmt::Type kind ) {
-	Statement * ret = new BranchStmt( "", kind );
+ast::Stmt * build_branch( const CodeLocation & location, ast::BranchStmt::Kind kind ) {
+	return new ast::BranchStmt( location,
+		kind,
+		ast::Label( location )
+	);
+} // build_branch
+
+ast::Stmt * build_branch( const CodeLocation & location, string * identifier, ast::BranchStmt::Kind kind ) {
+	ast::Stmt * ret = new ast::BranchStmt( location,
+		kind,
+		ast::Label( location, *identifier )
+	);
+	delete identifier; 									// allocated by lexer
 	return ret;
 } // build_branch
 
-Statement * build_branch( string * identifier, BranchStmt::Type kind ) {
-	Statement * ret = new BranchStmt( * identifier, kind );
-	delete identifier;									// allocated by lexer
-	return ret;
-} // build_branch
-
-Statement * build_computedgoto( ExpressionNode * ctl ) {
-	return new BranchStmt( maybeMoveBuild( ctl ), BranchStmt::Goto );
+ast::Stmt * build_computedgoto( ExpressionNode * ctl ) {
+	ast::Expr * expr = maybeMoveBuild( ctl );
+	return new ast::BranchStmt( expr->location, expr );
 } // build_computedgoto
 
-Statement * build_return( ExpressionNode * ctl ) {
-	list< Expression * > exps;
+ast::Stmt * build_return( const CodeLocation & location, ExpressionNode * ctl ) {
+	std::vector<ast::ptr<ast::Expr>> exps;
 	buildMoveList( ctl, exps );
-	return new ReturnStmt( exps.size() > 0 ? exps.back() : nullptr );
+	return new ast::ReturnStmt( location,
+		exps.size() > 0 ? exps.back().release() : nullptr
+	);
 } // build_return
 
-Statement * build_throw( ExpressionNode * ctl ) {
-	list< Expression * > exps;
+static ast::Stmt * build_throw_stmt(
+		const CodeLocation & location,
+		ExpressionNode * ctl,
+		ast::ExceptionKind kind ) {
+	std::vector<ast::ptr<ast::Expr>> exps;
 	buildMoveList( ctl, exps );
 	assertf( exps.size() < 2, "CFA internal error: leaking memory" );
-	return new ThrowStmt( ThrowStmt::Terminate, !exps.empty() ? exps.back() : nullptr );
+	return new ast::ThrowStmt( location,
+		kind,
+		!exps.empty() ? exps.back().release() : nullptr,
+		(ast::Expr *)nullptr
+	);
+}
+
+ast::Stmt * build_throw( const CodeLocation & loc, ExpressionNode * ctl ) {
+	return build_throw_stmt( loc, ctl, ast::Terminate );
 } // build_throw
 
-Statement * build_resume( ExpressionNode * ctl ) {
-	list< Expression * > exps;
-	buildMoveList( ctl, exps );
-	assertf( exps.size() < 2, "CFA internal error: leaking memory" );
-	return new ThrowStmt( ThrowStmt::Resume, !exps.empty() ? exps.back() : nullptr );
+ast::Stmt * build_resume( const CodeLocation & loc, ExpressionNode * ctl ) {
+	return build_throw_stmt( loc, ctl, ast::Resume );
 } // build_resume
 
-Statement * build_resume_at( ExpressionNode * ctl, ExpressionNode * target ) {
+ast::Stmt * build_resume_at( ExpressionNode * ctl, ExpressionNode * target ) {
 	(void)ctl;
 	(void)target;
@@ -233,85 +326,97 @@
 } // build_resume_at
 
-Statement * build_try( StatementNode * try_, StatementNode * catch_, StatementNode * finally_ ) {
-	list< CatchStmt * > aststmt;
-	buildMoveList< CatchStmt, StatementNode >( catch_, aststmt );
-	CompoundStmt * tryBlock = strict_dynamic_cast< CompoundStmt * >( maybeMoveBuild( try_ ) );
-	FinallyStmt * finallyBlock = dynamic_cast< FinallyStmt * >( maybeMoveBuild( finally_ ) );
-	return new TryStmt( tryBlock, aststmt, finallyBlock );
+ast::Stmt * build_try( const CodeLocation & location, StatementNode * try_, StatementNode * catch_, StatementNode * finally_ ) {
+	std::vector<ast::ptr<ast::CatchClause>> aststmt;
+	buildMoveClauseList( catch_, aststmt );
+	ast::CompoundStmt * tryBlock = strict_dynamic_cast<ast::CompoundStmt *>( maybeMoveBuild( try_ ) );
+	ast::FinallyClause * finallyBlock = nullptr;
+	if ( finally_ ) {
+		finallyBlock = dynamic_cast<ast::FinallyClause *>( finally_->clause.release() );
+	}
+	return new ast::TryStmt( location,
+		tryBlock,
+		std::move( aststmt ),
+		finallyBlock
+	);
 } // build_try
 
-Statement * build_catch( CatchStmt::Kind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body ) {
-	list< Statement * > aststmt;
-	buildMoveList< Statement, StatementNode >( body, aststmt );
+ast::CatchClause * build_catch( const CodeLocation & location, ast::ExceptionKind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body ) {
+	std::vector<ast::ptr<ast::Stmt>> aststmt;
+	buildMoveList( body, aststmt );
 	assert( aststmt.size() == 1 );
-	return new CatchStmt( kind, maybeMoveBuild( decl ), maybeMoveBuild( cond ), aststmt.front() );
+	return new ast::CatchClause( location,
+		kind,
+		maybeMoveBuild( decl ),
+		maybeMoveBuild( cond ),
+		aststmt.front().release()
+	);
 } // build_catch
 
-Statement * build_finally( StatementNode * stmt ) {
-	list< Statement * > aststmt;
-	buildMoveList< Statement, StatementNode >( stmt, aststmt );
+ast::FinallyClause * build_finally( const CodeLocation & location, StatementNode * stmt ) {
+	std::vector<ast::ptr<ast::Stmt>> aststmt;
+	buildMoveList( stmt, aststmt );
 	assert( aststmt.size() == 1 );
-	return new FinallyStmt( dynamic_cast< CompoundStmt * >( aststmt.front() ) );
+	return new ast::FinallyClause( location,
+		aststmt.front().strict_as<ast::CompoundStmt>()
+	);
 } // build_finally
 
-SuspendStmt * build_suspend( StatementNode * then, SuspendStmt::Type type ) {
-	auto node = new SuspendStmt();
-
-	node->type = type;
-
-	list< Statement * > stmts;
-	buildMoveList< Statement, StatementNode >( then, stmts );
+ast::SuspendStmt * build_suspend( const CodeLocation & location, StatementNode * then, ast::SuspendStmt::Type type ) {
+	std::vector<ast::ptr<ast::Stmt>> stmts;
+	buildMoveList( then, stmts );
+	ast::CompoundStmt const * then2 = nullptr;
 	if(!stmts.empty()) {
 		assert( stmts.size() == 1 );
-		node->then = dynamic_cast< CompoundStmt * >( stmts.front() );
+		then2 = stmts.front().strict_as<ast::CompoundStmt>();
 	}
-
+	auto node = new ast::SuspendStmt( location, then2, ast::SuspendStmt::None );
+	node->type = type;
 	return node;
 } // build_suspend
 
-WaitForStmt * build_waitfor( WaitForStmt * existing, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt ) {
-	WaitForStmt::Target target;
-	target.function = maybeBuild( targetExpr );
+ast::WaitForStmt * build_waitfor( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt ) {
+	auto clause = new ast::WaitForClause( location );
+	clause->target_func = maybeBuild( targetExpr );
+	clause->stmt = maybeMoveBuild( stmt );
+	clause->cond = notZeroExpr( maybeMoveBuild( when ) );
 
 	ExpressionNode * next = dynamic_cast<ExpressionNode *>( targetExpr->get_next() );
 	targetExpr->set_next( nullptr );
-	buildMoveList< Expression >( next, target.arguments );
+	buildMoveList( next, clause->target_args );
 
 	delete targetExpr;
 
-	existing->clauses.insert( existing->clauses.begin(), WaitForStmt::Clause{
-		std::move( target ),
-		maybeMoveBuild( stmt ),
-		notZeroExpr( maybeMoveBuild( when ) )
-	});
+	existing->clauses.insert( existing->clauses.begin(), clause );
 
 	return existing;
 } // build_waitfor
 
-WaitForStmt * build_waitfor_else( WaitForStmt * existing, ExpressionNode * when, StatementNode * stmt ) {
-	existing->orelse.statement  = maybeMoveBuild( stmt );
-	existing->orelse.condition  = notZeroExpr( maybeMoveBuild( when ) );
-
+ast::WaitForStmt * build_waitfor_else( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, StatementNode * stmt ) {
+	existing->else_stmt = maybeMoveBuild( stmt );
+	existing->else_cond = notZeroExpr( maybeMoveBuild( when ) );
+
+	(void)location;
 	return existing;
 } // build_waitfor_else
 
-WaitForStmt * build_waitfor_timeout( WaitForStmt * existing, ExpressionNode * when, ExpressionNode * timeout, StatementNode * stmt ) {
-	existing->timeout.time      = maybeMoveBuild( timeout );
-	existing->timeout.statement = maybeMoveBuild( stmt );
-	existing->timeout.condition = notZeroExpr( maybeMoveBuild( when ) );
-
+ast::WaitForStmt * build_waitfor_timeout( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * timeout, StatementNode * stmt ) {
+	existing->timeout_time = maybeMoveBuild( timeout );
+	existing->timeout_stmt = maybeMoveBuild( stmt );
+	existing->timeout_cond = notZeroExpr( maybeMoveBuild( when ) );
+
+	(void)location;
 	return existing;
 } // build_waitfor_timeout
 
-Statement * build_with( ExpressionNode * exprs, StatementNode * stmt ) {
-	list< Expression * > e;
+ast::Stmt * build_with( const CodeLocation & location, ExpressionNode * exprs, StatementNode * stmt ) {
+	std::vector<ast::ptr<ast::Expr>> e;
 	buildMoveList( exprs, e );
-	Statement * s = maybeMoveBuild( stmt );
-	return new DeclStmt( new WithStmt( e, s ) );
+	ast::Stmt * s = maybeMoveBuild( stmt );
+	return new ast::DeclStmt( location, new ast::WithStmt( location, std::move( e ), s ) );
 } // build_with
 
-Statement * build_compound( StatementNode * first ) {
-	CompoundStmt * cs = new CompoundStmt();
-	buildMoveList( first, cs->get_kids() );
+ast::Stmt * build_compound( const CodeLocation & location, StatementNode * first ) {
+	auto cs = new ast::CompoundStmt( location );
+	buildMoveList( first, cs->kids );
 	return cs;
 } // build_compound
@@ -321,11 +426,9 @@
 // statement and wrap it into a compound statement to insert additional code. Hence, all control structures have a
 // conical form for code generation.
-StatementNode * maybe_build_compound( StatementNode * first ) {
+StatementNode * maybe_build_compound( const CodeLocation & location, StatementNode * first ) {
 	// Optimization: if the control-structure statement is a compound statement, do not wrap it.
 	// e.g., if (...) {...} do not wrap the existing compound statement.
-	if ( ! dynamic_cast<CompoundStmt *>( first->stmt.get() ) ) { // unique_ptr
-		CompoundStmt * cs = new CompoundStmt();
-		buildMoveList( first, cs->get_kids() );
-		return new StatementNode( cs );
+	if ( !dynamic_cast<ast::CompoundStmt *>( first->stmt.get() ) ) { // unique_ptr
+		return new StatementNode( build_compound( location, first ) );
 	} // if
 	return first;
@@ -333,23 +436,32 @@
 
 // Question
-Statement * build_asm( bool voltile, Expression * instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) {
-	list< Expression * > out, in;
-	list< ConstantExpr * > clob;
+ast::Stmt * build_asm( const CodeLocation & location, bool voltile, ast::Expr * instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) {
+	std::vector<ast::ptr<ast::Expr>> out, in;
+	std::vector<ast::ptr<ast::ConstantExpr>> clob;
 
 	buildMoveList( output, out );
 	buildMoveList( input, in );
 	buildMoveList( clobber, clob );
-	return new AsmStmt( voltile, instruction, out, in, clob, gotolabels ? gotolabels->labels : noLabels );
+	return new ast::AsmStmt( location,
+		voltile,
+		instruction,
+		std::move( out ),
+		std::move( in ),
+		std::move( clob ),
+		gotolabels ? gotolabels->labels : std::vector<ast::Label>()
+	);
 } // build_asm
 
-Statement * build_directive( string * directive ) {
-	return new DirectiveStmt( *directive );
+ast::Stmt * build_directive( const CodeLocation & location, string * directive ) {
+	auto stmt = new ast::DirectiveStmt( location, *directive );
+	delete directive;
+	return stmt;
 } // build_directive
 
-Statement * build_mutex( ExpressionNode * exprs, StatementNode * stmt ) {
-	list< Expression * > expList;
+ast::Stmt * build_mutex( const CodeLocation & location, ExpressionNode * exprs, StatementNode * stmt ) {
+	std::vector<ast::ptr<ast::Expr>> expList;
 	buildMoveList( exprs, expList );
-	Statement * body = maybeMoveBuild( stmt );
-	return new MutexStmt( body, expList );
+	ast::Stmt * body = maybeMoveBuild( stmt );
+	return new ast::MutexStmt( location, body, std::move( expList ) );
 } // build_mutex
 
Index: src/Parser/TypeData.cc
===================================================================
--- src/Parser/TypeData.cc	(revision 70056edafe6b115773f5da41e81a7b2adf5c08f5)
+++ src/Parser/TypeData.cc	(revision e02e13fc53b4a6d659a7753b2c843a4b7e203c0d)
@@ -9,21 +9,21 @@
 // Author           : Rodolfo G. Esteves
 // Created On       : Sat May 16 15:12:51 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Sun Feb 19 11:00:46 2023
-// Update Count     : 679
+// Last Modified By : Andrew Beach
+// Last Modified On : Tue Apr  4 13:39:00 2023
+// Update Count     : 680
 //
+
+#include "TypeData.h"
 
 #include <cassert>                 // for assert
 #include <ostream>                 // for operator<<, ostream, basic_ostream
 
+#include "AST/Decl.hpp"            // for AggregateDecl, ObjectDecl, TypeDe...
+#include "AST/Init.hpp"            // for SingleInit, ListInit
+#include "AST/Print.hpp"           // for print
 #include "Common/SemanticError.h"  // for SemanticError
-#include "Common/utility.h"        // for maybeClone, maybeBuild, maybeMoveB...
+#include "Common/utility.h"        // for splice, spliceBegin
+#include "Parser/parserutility.h"  // for maybeCopy, maybeBuild, maybeMoveB...
 #include "Parser/ParseNode.h"      // for DeclarationNode, ExpressionNode
-#include "SynTree/Declaration.h"   // for TypeDecl, ObjectDecl, FunctionDecl
-#include "SynTree/Expression.h"    // for Expression, ConstantExpr (ptr only)
-#include "SynTree/Initializer.h"   // for SingleInit, Initializer (ptr only)
-#include "SynTree/Statement.h"     // for CompoundStmt, Statement
-#include "SynTree/Type.h"          // for BasicType, Type, Type::ForallList
-#include "TypeData.h"
 
 class Attribute;
@@ -60,5 +60,5 @@
 		break;
 	case Aggregate:
-		aggregate.kind = AggregateDecl::NoAggregate;
+		aggregate.kind = ast::AggregateDecl::NoAggregate;
 		aggregate.name = nullptr;
 		aggregate.params = nullptr;
@@ -89,6 +89,6 @@
 		typeexpr = nullptr;
 		break;
+	case Vtable:
 	case Builtin:
-	case Vtable:
 		// No unique data to initialize.
 		break;
@@ -111,7 +111,6 @@
 	case EnumConstant:
 	case GlobalScope:
+	case Basic:
 		// No unique data to deconstruct.
-		break;
-	case Basic:
 		break;
 	case Array:
@@ -250,7 +249,5 @@
 
 void TypeData::print( ostream &os, int indent ) const {
-	for ( int i = 0; i < Type::NumTypeQualifier; i += 1 ) {
-		if ( qualifiers[i] ) os << Type::QualifiersNames[ i ] << ' ';
-	} // for
+	ast::print( os, qualifiers );
 
 	if ( forall ) {
@@ -325,5 +322,5 @@
 		break;
 	case Aggregate:
-		os << AggregateDecl::aggrString( aggregate.kind ) << ' ' << *aggregate.name << endl;
+		os << ast::AggregateDecl::aggrString( aggregate.kind ) << ' ' << *aggregate.name << endl;
 		if ( aggregate.params ) {
 			os << string( indent + 2, ' ' ) << "with type parameters" << endl;
@@ -472,45 +469,315 @@
 
 
-template< typename ForallList >
-void buildForall( const DeclarationNode * firstNode, ForallList &outputList ) {
-	buildList( firstNode, outputList );
+void buildForall(
+		const DeclarationNode * firstNode,
+		std::vector<ast::ptr<ast::TypeInstType>> &outputList ) {
+	{
+		std::vector<ast::ptr<ast::Type>> tmpList;
+		buildTypeList( firstNode, tmpList );
+		for ( auto tmp : tmpList ) {
+			outputList.emplace_back(
+				strict_dynamic_cast<const ast::TypeInstType *>(
+					tmp.release() ) );
+		}
+	}
 	auto n = firstNode;
-	for ( typename ForallList::iterator i = outputList.begin(); i != outputList.end(); ++i, n = (DeclarationNode*)n->get_next() ) {
-		TypeDecl * td = static_cast<TypeDecl *>(*i);
-		if ( n->variable.tyClass == TypeDecl::Otype ) {
-			// add assertion parameters to `type' tyvars in reverse order
-			// add dtor:  void ^?{}(T *)
-			FunctionType * dtorType = new FunctionType( Type::Qualifiers(), false );
-			dtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );
-			td->get_assertions().push_front( new FunctionDecl( "^?{}", Type::StorageClasses(), LinkageSpec::Cforall, dtorType, nullptr ) );
-
-			// add copy ctor:  void ?{}(T *, T)
-			FunctionType * copyCtorType = new FunctionType( Type::Qualifiers(), false );
-			copyCtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );
-			copyCtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) );
-			td->get_assertions().push_front( new FunctionDecl( "?{}", Type::StorageClasses(), LinkageSpec::Cforall, copyCtorType, nullptr ) );
-
-			// add default ctor:  void ?{}(T *)
-			FunctionType * ctorType = new FunctionType( Type::Qualifiers(), false );
-			ctorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );
-			td->get_assertions().push_front( new FunctionDecl( "?{}", Type::StorageClasses(), LinkageSpec::Cforall, ctorType, nullptr ) );
-
-			// add assignment operator:  T * ?=?(T *, T)
-			FunctionType * assignType = new FunctionType( Type::Qualifiers(), false );
-			assignType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );
-			assignType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) );
-			assignType->get_returnVals().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) );
-			td->get_assertions().push_front( new FunctionDecl( "?=?", Type::StorageClasses(), LinkageSpec::Cforall, assignType, nullptr ) );
-		} // if
+	for ( auto i = outputList.begin() ;
+			i != outputList.end() ;
+			++i, n = (DeclarationNode*)n->get_next() ) {
+		// Only the object type class adds additional assertions.
+		if ( n->variable.tyClass != ast::TypeDecl::Otype ) {
+			continue;
+		}
+
+		ast::TypeDecl const * td = i->strict_as<ast::TypeDecl>();
+		std::vector<ast::ptr<ast::DeclWithType>> newAssertions;
+		auto mutTypeDecl = ast::mutate( td );
+		const CodeLocation & location = mutTypeDecl->location;
+		*i = mutTypeDecl;
+
+		// add assertion parameters to `type' tyvars in reverse order
+		// add assignment operator:  T * ?=?(T *, T)
+		newAssertions.push_back( new ast::FunctionDecl(
+			location,
+			"?=?",
+			{}, // forall
+			{}, // assertions
+			{
+				new ast::ObjectDecl(
+					location,
+					"",
+					new ast::ReferenceType( i->get() ),
+					(ast::Init *)nullptr,
+					ast::Storage::Classes(),
+					ast::Linkage::Cforall,
+					(ast::Expr *)nullptr
+				),
+				new ast::ObjectDecl(
+					location,
+					"",
+					i->get(),
+					(ast::Init *)nullptr,
+					ast::Storage::Classes(),
+					ast::Linkage::Cforall,
+					(ast::Expr *)nullptr
+				),
+			}, // params
+			{
+				new ast::ObjectDecl(
+					location,
+					"",
+					i->get(),
+					(ast::Init *)nullptr,
+					ast::Storage::Classes(),
+					ast::Linkage::Cforall,
+					(ast::Expr *)nullptr
+				),
+			}, // returns
+			(ast::CompoundStmt *)nullptr,
+			ast::Storage::Classes(),
+			ast::Linkage::Cforall
+		) );
+
+		// add default ctor:  void ?{}(T *)
+		newAssertions.push_back( new ast::FunctionDecl(
+			location,
+			"?{}",
+			{}, // forall
+			{}, // assertions
+			{
+				new ast::ObjectDecl(
+					location,
+					"",
+					new ast::ReferenceType( i->get() ),
+					(ast::Init *)nullptr,
+					ast::Storage::Classes(),
+					ast::Linkage::Cforall,
+					(ast::Expr *)nullptr
+				),
+			}, // params
+			{}, // returns
+			(ast::CompoundStmt *)nullptr,
+			ast::Storage::Classes(),
+			ast::Linkage::Cforall
+		) );
+
+		// add copy ctor:  void ?{}(T *, T)
+		newAssertions.push_back( new ast::FunctionDecl(
+			location,
+			"?{}",
+			{}, // forall
+			{}, // assertions
+			{
+				new ast::ObjectDecl(
+					location,
+					"",
+					new ast::ReferenceType( i->get() ),
+					(ast::Init *)nullptr,
+					ast::Storage::Classes(),
+					ast::Linkage::Cforall,
+					(ast::Expr *)nullptr
+				),
+				new ast::ObjectDecl(
+					location,
+					"",
+					i->get(),
+					(ast::Init *)nullptr,
+					ast::Storage::Classes(),
+					ast::Linkage::Cforall,
+					(ast::Expr *)nullptr
+				),
+			}, // params
+			{}, // returns
+			(ast::CompoundStmt *)nullptr,
+			ast::Storage::Classes(),
+			ast::Linkage::Cforall
+		) );
+
+		// add dtor:  void ^?{}(T *)
+		newAssertions.push_back( new ast::FunctionDecl(
+			location,
+			"^?{}",
+			{}, // forall
+			{}, // assertions
+			{
+				new ast::ObjectDecl(
+					location,
+					"",
+					new ast::ReferenceType( i->get() ),
+					(ast::Init *)nullptr,
+					ast::Storage::Classes(),
+					ast::Linkage::Cforall,
+					(ast::Expr *)nullptr
+				),
+			}, // params
+			{}, // returns
+			(ast::CompoundStmt *)nullptr,
+			ast::Storage::Classes(),
+			ast::Linkage::Cforall
+		) );
+
+		spliceBegin( mutTypeDecl->assertions, newAssertions );
+	} // for
+}
+
+
+void buildForall(
+		const DeclarationNode * firstNode,
+		std::vector<ast::ptr<ast::TypeDecl>> &outputForall ) {
+	buildList( firstNode, outputForall );
+	auto n = firstNode;
+	for ( auto i = outputForall.begin() ;
+			i != outputForall.end() ;
+			++i, n = (DeclarationNode*)n->get_next() ) {
+		// Only the object type class adds additional assertions.
+		if ( n->variable.tyClass != ast::TypeDecl::Otype ) {
+			continue;
+		}
+
+		ast::TypeDecl const * td = i->strict_as<ast::TypeDecl>();
+		std::vector<ast::ptr<ast::DeclWithType>> newAssertions;
+		auto mutTypeDecl = ast::mutate( td );
+		const CodeLocation & location = mutTypeDecl->location;
+		*i = mutTypeDecl;
+
+		// add assertion parameters to `type' tyvars in reverse order
+		// add assignment operator:  T * ?=?(T *, T)
+		newAssertions.push_back( new ast::FunctionDecl(
+			location,
+			"?=?",
+			{}, // forall
+			{}, // assertions
+			{
+				new ast::ObjectDecl(
+					location,
+					"",
+					new ast::ReferenceType( new ast::TypeInstType( td->name, *i ) ),
+					(ast::Init *)nullptr,
+					ast::Storage::Classes(),
+					ast::Linkage::Cforall,
+					(ast::Expr *)nullptr
+				),
+				new ast::ObjectDecl(
+					location,
+					"",
+					new ast::TypeInstType( td->name, *i ),
+					(ast::Init *)nullptr,
+					ast::Storage::Classes(),
+					ast::Linkage::Cforall,
+					(ast::Expr *)nullptr
+				),
+			}, // params
+			{
+				new ast::ObjectDecl(
+					location,
+					"",
+					new ast::TypeInstType( td->name, *i ),
+					(ast::Init *)nullptr,
+					ast::Storage::Classes(),
+					ast::Linkage::Cforall,
+					(ast::Expr *)nullptr
+				),
+			}, // returns
+			(ast::CompoundStmt *)nullptr,
+			ast::Storage::Classes(),
+			ast::Linkage::Cforall
+		) );
+
+		// add default ctor:  void ?{}(T *)
+		newAssertions.push_back( new ast::FunctionDecl(
+			location,
+			"?{}",
+			{}, // forall
+			{}, // assertions
+			{
+				new ast::ObjectDecl(
+					location,
+					"",
+					new ast::ReferenceType(
+						new ast::TypeInstType( td->name, i->get() ) ),
+					(ast::Init *)nullptr,
+					ast::Storage::Classes(),
+					ast::Linkage::Cforall,
+					(ast::Expr *)nullptr
+				),
+			}, // params
+			{}, // returns
+			(ast::CompoundStmt *)nullptr,
+			ast::Storage::Classes(),
+			ast::Linkage::Cforall
+		) );
+
+		// add copy ctor:  void ?{}(T *, T)
+		newAssertions.push_back( new ast::FunctionDecl(
+			location,
+			"?{}",
+			{}, // forall
+			{}, // assertions
+			{
+				new ast::ObjectDecl(
+					location,
+					"",
+					new ast::ReferenceType(
+						new ast::TypeInstType( td->name, *i ) ),
+					(ast::Init *)nullptr,
+					ast::Storage::Classes(),
+					ast::Linkage::Cforall,
+					(ast::Expr *)nullptr
+				),
+				new ast::ObjectDecl(
+					location,
+					"",
+					new ast::TypeInstType( td->name, *i ),
+					(ast::Init *)nullptr,
+					ast::Storage::Classes(),
+					ast::Linkage::Cforall,
+					(ast::Expr *)nullptr
+				),
+			}, // params
+			{}, // returns
+			(ast::CompoundStmt *)nullptr,
+			ast::Storage::Classes(),
+			ast::Linkage::Cforall
+		) );
+
+		// add dtor:  void ^?{}(T *)
+		newAssertions.push_back( new ast::FunctionDecl(
+			location,
+			"^?{}",
+			{}, // forall
+			{}, // assertions
+			{
+				new ast::ObjectDecl(
+					location,
+					"",
+					new ast::ReferenceType(
+						new ast::TypeInstType( i->get() )
+					),
+					(ast::Init *)nullptr,
+					ast::Storage::Classes(),
+					ast::Linkage::Cforall,
+					(ast::Expr *)nullptr
+				),
+			}, // params
+			{}, // returns
+			(ast::CompoundStmt *)nullptr,
+			ast::Storage::Classes(),
+			ast::Linkage::Cforall
+		) );
+
+		spliceBegin( mutTypeDecl->assertions, newAssertions );
 	} // for
 } // buildForall
 
 
-Type * typebuild( const TypeData * td ) {
+ast::Type * typebuild( const TypeData * td ) {
 	assert( td );
 	switch ( td->kind ) {
 	case TypeData::Unknown:
 		// fill in implicit int
-		return new BasicType( buildQualifiers( td ), BasicType::SignedInt );
+		return new ast::BasicType(
+			ast::BasicType::SignedInt,
+			buildQualifiers( td )
+		);
 	case TypeData::Basic:
 		return buildBasicType( td );
@@ -522,9 +789,9 @@
 		return buildReference( td );
 	case TypeData::Function:
-		return buildFunction( td );
+		return buildFunctionType( td );
 	case TypeData::AggregateInst:
 		return buildAggInst( td );
 	case TypeData::EnumConstant:
-		return new EnumInstType( buildQualifiers( td ), "" );
+		return new ast::EnumInstType( "", buildQualifiers( td ) );
 	case TypeData::SymbolicInst:
 		return buildSymbolicInst( td );
@@ -539,14 +806,18 @@
 		switch ( td->builtintype ) {
 		case DeclarationNode::Zero:
-			return new ZeroType( noQualifiers );
+			return new ast::ZeroType();
 		case DeclarationNode::One:
-			return new OneType( noQualifiers );
+			return new ast::OneType();
 		default:
-			return new VarArgsType( buildQualifiers( td ) );
+			return new ast::VarArgsType( buildQualifiers( td ) );
 		} // switch
 	case TypeData::GlobalScope:
-		return new GlobalScopeType();
+		return new ast::GlobalScopeType();
 	case TypeData::Qualified:
-		return new QualifiedType( buildQualifiers( td ), typebuild( td->qualified.parent ), typebuild( td->qualified.child ) );
+		return new ast::QualifiedType(
+			typebuild( td->qualified.parent ),
+			typebuild( td->qualified.child ),
+			buildQualifiers( td )
+		);
 	case TypeData::Symbolic:
 	case TypeData::Enum:
@@ -587,5 +858,5 @@
 
 
-Type::Qualifiers buildQualifiers( const TypeData * td ) {
+ast::CV::Qualifiers buildQualifiers( const TypeData * td ) {
 	return td->qualifiers;
 } // buildQualifiers
@@ -596,6 +867,6 @@
 } // genTSError
 
-Type * buildBasicType( const TypeData * td ) {
-	BasicType::Kind ret;
+ast::Type * buildBasicType( const TypeData * td ) {
+	ast::BasicType::Kind ret;
 
 	switch ( td->basictype ) {
@@ -607,5 +878,5 @@
 			genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
 		} // if
-		return new VoidType( buildQualifiers( td ) );
+		return new ast::VoidType( buildQualifiers( td ) );
 		break;
 
@@ -618,5 +889,5 @@
 		} // if
 
-		ret = BasicType::Bool;
+		ret = ast::BasicType::Bool;
 		break;
 
@@ -625,5 +896,5 @@
 		// character types. The implementation shall define char to have the same range, representation, and behavior as
 		// either signed char or unsigned char.
-		static BasicType::Kind chartype[] = { BasicType::SignedChar, BasicType::UnsignedChar, BasicType::Char };
+		static ast::BasicType::Kind chartype[] = { ast::BasicType::SignedChar, ast::BasicType::UnsignedChar, ast::BasicType::Char };
 
 		if ( td->length != DeclarationNode::NoLength ) {
@@ -635,7 +906,7 @@
 
 	case DeclarationNode::Int:
-		static BasicType::Kind inttype[2][4] = {
-			{ BasicType::ShortSignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt, BasicType::SignedInt },
-			{ BasicType::ShortUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::UnsignedInt },
+		static ast::BasicType::Kind inttype[2][4] = {
+			{ ast::BasicType::ShortSignedInt, ast::BasicType::LongSignedInt, ast::BasicType::LongLongSignedInt, ast::BasicType::SignedInt },
+			{ ast::BasicType::ShortUnsignedInt, ast::BasicType::LongUnsignedInt, ast::BasicType::LongLongUnsignedInt, ast::BasicType::UnsignedInt },
 		};
 
@@ -648,5 +919,5 @@
 
 	case DeclarationNode::Int128:
-		ret = td->signedness == DeclarationNode::Unsigned ? BasicType::UnsignedInt128 : BasicType::SignedInt128;
+		ret = td->signedness == DeclarationNode::Unsigned ? ast::BasicType::UnsignedInt128 : ast::BasicType::SignedInt128;
 		if ( td->length != DeclarationNode::NoLength ) {
 			genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
@@ -666,7 +937,7 @@
 	case DeclarationNode::uFloat128:
 	case DeclarationNode::uFloat128x:
-		static BasicType::Kind floattype[2][12] = {
-			{ BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, (BasicType::Kind)-1, (BasicType::Kind)-1, BasicType::uFloat16Complex, BasicType::uFloat32Complex, BasicType::uFloat32xComplex, BasicType::uFloat64Complex, BasicType::uFloat64xComplex, BasicType::uFloat128Complex, BasicType::uFloat128xComplex, },
-			{ BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::uuFloat80, BasicType::uuFloat128, BasicType::uFloat16, BasicType::uFloat32, BasicType::uFloat32x, BasicType::uFloat64, BasicType::uFloat64x, BasicType::uFloat128, BasicType::uFloat128x, },
+		static ast::BasicType::Kind floattype[2][12] = {
+			{ ast::BasicType::FloatComplex, ast::BasicType::DoubleComplex, ast::BasicType::LongDoubleComplex, (ast::BasicType::Kind)-1, (ast::BasicType::Kind)-1, ast::BasicType::uFloat16Complex, ast::BasicType::uFloat32Complex, ast::BasicType::uFloat32xComplex, ast::BasicType::uFloat64Complex, ast::BasicType::uFloat64xComplex, ast::BasicType::uFloat128Complex, ast::BasicType::uFloat128xComplex, },
+			{ ast::BasicType::Float, ast::BasicType::Double, ast::BasicType::LongDouble, ast::BasicType::uuFloat80, ast::BasicType::uuFloat128, ast::BasicType::uFloat16, ast::BasicType::uFloat32, ast::BasicType::uFloat32x, ast::BasicType::uFloat64, ast::BasicType::uFloat64x, ast::BasicType::uFloat128, ast::BasicType::uFloat128x, },
 		};
 
@@ -709,68 +980,99 @@
 	} // switch
 
-	BasicType * bt = new BasicType( buildQualifiers( td ), ret );
-	buildForall( td->forall, bt->get_forall() );
+	ast::BasicType * bt = new ast::BasicType( ret, buildQualifiers( td ) );
 	return bt;
 } // buildBasicType
 
 
-PointerType * buildPointer( const TypeData * td ) {
-	PointerType * pt;
+ast::PointerType * buildPointer( const TypeData * td ) {
+	ast::PointerType * pt;
 	if ( td->base ) {
-		pt = new PointerType( buildQualifiers( td ), typebuild( td->base ) );
+		pt = new ast::PointerType(
+			typebuild( td->base ),
+			buildQualifiers( td )
+		);
 	} else {
-		pt = new PointerType( buildQualifiers( td ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
+		pt = new ast::PointerType(
+			new ast::BasicType( ast::BasicType::SignedInt ),
+			buildQualifiers( td )
+		);
 	} // if
-	buildForall( td->forall, pt->get_forall() );
 	return pt;
 } // buildPointer
 
 
-ArrayType * buildArray( const TypeData * td ) {
-	ArrayType * at;
+ast::ArrayType * buildArray( const TypeData * td ) {
+	ast::ArrayType * at;
 	if ( td->base ) {
-		at = new ArrayType( buildQualifiers( td ), typebuild( td->base ), maybeBuild( td->array.dimension ),
-							td->array.isVarLen, td->array.isStatic );
+		at = new ast::ArrayType(
+			typebuild( td->base ),
+			maybeBuild( td->array.dimension ),
+			td->array.isVarLen ? ast::VariableLen : ast::FixedLen,
+			td->array.isStatic ? ast::StaticDim : ast::DynamicDim,
+			buildQualifiers( td )
+		);
 	} else {
-		at = new ArrayType( buildQualifiers( td ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ),
-							maybeBuild( td->array.dimension ), td->array.isVarLen, td->array.isStatic );
+		at = new ast::ArrayType(
+			new ast::BasicType( ast::BasicType::SignedInt ),
+			maybeBuild( td->array.dimension ),
+			td->array.isVarLen ? ast::VariableLen : ast::FixedLen,
+			td->array.isStatic ? ast::StaticDim : ast::DynamicDim,
+			buildQualifiers( td )
+		);
 	} // if
-	buildForall( td->forall, at->get_forall() );
 	return at;
 } // buildArray
 
 
-ReferenceType * buildReference( const TypeData * td ) {
-	ReferenceType * rt;
+ast::ReferenceType * buildReference( const TypeData * td ) {
+	ast::ReferenceType * rt;
 	if ( td->base ) {
-		rt = new ReferenceType( buildQualifiers( td ), typebuild( td->base ) );
+		rt = new ast::ReferenceType(
+			typebuild( td->base ),
+			buildQualifiers( td )
+		);
 	} else {
-		rt = new ReferenceType( buildQualifiers( td ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
+		rt = new ast::ReferenceType(
+			new ast::BasicType( ast::BasicType::SignedInt ),
+			buildQualifiers( td )
+		);
 	} // if
-	buildForall( td->forall, rt->get_forall() );
 	return rt;
 } // buildReference
 
 
-AggregateDecl * buildAggregate( const TypeData * td, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ) {
+ast::AggregateDecl * buildAggregate( const TypeData * td, std::vector<ast::ptr<ast::Attribute>> attributes, ast::Linkage::Spec linkage ) {
 	assert( td->kind == TypeData::Aggregate );
-	AggregateDecl * at;
+	ast::AggregateDecl * at;
 	switch ( td->aggregate.kind ) {
-	case AggregateDecl::Struct:
-	case AggregateDecl::Coroutine:
-	case AggregateDecl::Exception:
-	case AggregateDecl::Generator:
-	case AggregateDecl::Monitor:
-	case AggregateDecl::Thread:
-		at = new StructDecl( *td->aggregate.name, td->aggregate.kind, attributes, linkage );
-		buildForall( td->aggregate.params, at->get_parameters() );
-		break;
-	case AggregateDecl::Union:
-		at = new UnionDecl( *td->aggregate.name, attributes, linkage );
-		buildForall( td->aggregate.params, at->get_parameters() );
-		break;
-	case AggregateDecl::Trait:
-		at = new TraitDecl( *td->aggregate.name, attributes, linkage );
-		buildList( td->aggregate.params, at->get_parameters() );
+	case ast::AggregateDecl::Struct:
+	case ast::AggregateDecl::Coroutine:
+	case ast::AggregateDecl::Exception:
+	case ast::AggregateDecl::Generator:
+	case ast::AggregateDecl::Monitor:
+	case ast::AggregateDecl::Thread:
+		at = new ast::StructDecl( td->location,
+			*td->aggregate.name,
+			td->aggregate.kind,
+			std::move( attributes ),
+			linkage
+		);
+		buildForall( td->aggregate.params, at->params );
+		break;
+	case ast::AggregateDecl::Union:
+		at = new ast::UnionDecl( td->location,
+			*td->aggregate.name,
+			std::move( attributes ),
+			linkage
+		);
+		buildForall( td->aggregate.params, at->params );
+		break;
+	case ast::AggregateDecl::Trait:
+		at = new ast::TraitDecl( td->location,
+			*td->aggregate.name,
+			std::move( attributes ),
+			linkage
+		);
+		buildList( td->aggregate.params, at->params );
 		break;
 	default:
@@ -778,5 +1080,5 @@
 	} // switch
 
-	buildList( td->aggregate.fields, at->get_members() );
+	buildList( td->aggregate.fields, at->members );
 	at->set_body( td->aggregate.body );
 
@@ -785,27 +1087,44 @@
 
 
-ReferenceToType * buildComAggInst( const TypeData * type, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ) {
+ast::BaseInstType * buildComAggInst(
+		const TypeData * type,
+		std::vector<ast::ptr<ast::Attribute>> && attributes,
+		ast::Linkage::Spec linkage ) {
 	switch ( type->kind ) {
 	case TypeData::Enum:
 		if ( type->enumeration.body ) {
-			EnumDecl * typedecl = buildEnum( type, attributes, linkage );
-			return new EnumInstType( buildQualifiers( type ), typedecl );
+			ast::EnumDecl * typedecl =
+				buildEnum( type, std::move( attributes ), linkage );
+			return new ast::EnumInstType(
+				typedecl,
+				buildQualifiers( type )
+			);
 		} else {
-			return new EnumInstType( buildQualifiers( type ), *type->enumeration.name );
-		} // if
+			return new ast::EnumInstType(
+				*type->enumeration.name,
+				buildQualifiers( type )
+			);
+		} // if
+		break;
 	case TypeData::Aggregate:
 		if ( type->aggregate.body ) {
-			AggregateDecl * typedecl = buildAggregate( type, attributes, linkage );
+			ast::AggregateDecl * typedecl =
+				buildAggregate( type, std::move( attributes ), linkage );
 			switch ( type->aggregate.kind ) {
-			case AggregateDecl::Struct:
-			case AggregateDecl::Coroutine:
-			case AggregateDecl::Monitor:
-			case AggregateDecl::Thread:
-				return new StructInstType( buildQualifiers( type ), (StructDecl *)typedecl );
-			case AggregateDecl::Union:
-				return new UnionInstType( buildQualifiers( type ), (UnionDecl *)typedecl );
-			case AggregateDecl::Trait:
+			case ast::AggregateDecl::Struct:
+			case ast::AggregateDecl::Coroutine:
+			case ast::AggregateDecl::Monitor:
+			case ast::AggregateDecl::Thread:
+				return new ast::StructInstType(
+					strict_dynamic_cast<ast::StructDecl *>( typedecl ),
+					buildQualifiers( type )
+				);
+			case ast::AggregateDecl::Union:
+				return new ast::UnionInstType(
+					strict_dynamic_cast<ast::UnionDecl *>( typedecl ),
+					buildQualifiers( type )
+				);
+			case ast::AggregateDecl::Trait:
 				assert( false );
-				//return new TraitInstType( buildQualifiers( type ), (TraitDecl *)typedecl );
 				break;
 			default:
@@ -814,46 +1133,68 @@
 		} else {
 			switch ( type->aggregate.kind ) {
-			case AggregateDecl::Struct:
-			case AggregateDecl::Coroutine:
-			case AggregateDecl::Monitor:
-			case AggregateDecl::Thread:
-				return new StructInstType( buildQualifiers( type ), *type->aggregate.name );
-			case AggregateDecl::Union:
-				return new UnionInstType( buildQualifiers( type ), *type->aggregate.name );
-			case AggregateDecl::Trait:
-				return new TraitInstType( buildQualifiers( type ), *type->aggregate.name );
+			case ast::AggregateDecl::Struct:
+			case ast::AggregateDecl::Coroutine:
+			case ast::AggregateDecl::Monitor:
+			case ast::AggregateDecl::Thread:
+				return new ast::StructInstType(
+					*type->aggregate.name,
+					buildQualifiers( type )
+				);
+			case ast::AggregateDecl::Union:
+				return new ast::UnionInstType(
+					*type->aggregate.name,
+					buildQualifiers( type )
+				);
+			case ast::AggregateDecl::Trait:
+				return new ast::TraitInstType(
+					*type->aggregate.name,
+					buildQualifiers( type )
+				);
 			default:
 				assert( false );
 			} // switch
-		} // if
-		return nullptr;
+			break;
+		} // if
+		break;
 	default:
 		assert( false );
 	} // switch
+	assert( false );
 } // buildAggInst
 
 
-ReferenceToType * buildAggInst( const TypeData * td ) {
+ast::BaseInstType * buildAggInst( const TypeData * td ) {
 	assert( td->kind == TypeData::AggregateInst );
 
-	// ReferenceToType * ret = buildComAggInst( td->aggInst.aggregate, std::list< Attribute * >() );
-	ReferenceToType * ret = nullptr;
+	ast::BaseInstType * ret = nullptr;
 	TypeData * type = td->aggInst.aggregate;
 	switch ( type->kind ) {
 	case TypeData::Enum:
-		return new EnumInstType( buildQualifiers( type ), *type->enumeration.name );
+		return new ast::EnumInstType(
+			*type->enumeration.name,
+			buildQualifiers( type )
+		);
 	case TypeData::Aggregate:
 		switch ( type->aggregate.kind ) {
-		case AggregateDecl::Struct:
-		case AggregateDecl::Coroutine:
-		case AggregateDecl::Monitor:
-		case AggregateDecl::Thread:
-			ret = new StructInstType( buildQualifiers( type ), *type->aggregate.name );
+		case ast::AggregateDecl::Struct:
+		case ast::AggregateDecl::Coroutine:
+		case ast::AggregateDecl::Monitor:
+		case ast::AggregateDecl::Thread:
+			ret = new ast::StructInstType(
+				*type->aggregate.name,
+				buildQualifiers( type )
+			);
 			break;
-		case AggregateDecl::Union:
-			ret = new UnionInstType( buildQualifiers( type ), *type->aggregate.name );
+		case ast::AggregateDecl::Union:
+			ret = new ast::UnionInstType(
+				*type->aggregate.name,
+				buildQualifiers( type )
+			);
 			break;
-		case AggregateDecl::Trait:
-			ret = new TraitInstType( buildQualifiers( type ), *type->aggregate.name );
+		case ast::AggregateDecl::Trait:
+			ret = new ast::TraitInstType(
+				*type->aggregate.name,
+				buildQualifiers( type )
+			);
 			break;
 		default:
@@ -865,33 +1206,60 @@
 	} // switch
 
-	ret->set_hoistType( td->aggInst.hoistType );
-	buildList( td->aggInst.params, ret->get_parameters() );
-	buildForall( td->forall, ret->get_forall() );
+	ret->hoistType = td->aggInst.hoistType;
+	buildList( td->aggInst.params, ret->params );
 	return ret;
 } // buildAggInst
 
 
-NamedTypeDecl * buildSymbolic( const TypeData * td, std::list< Attribute * > attributes, const string & name, Type::StorageClasses scs, LinkageSpec::Spec linkage ) {
+ast::NamedTypeDecl * buildSymbolic(
+		const TypeData * td,
+		std::vector<ast::ptr<ast::Attribute>> attributes,
+		const std::string & name,
+		ast::Storage::Classes scs,
+		ast::Linkage::Spec linkage ) {
 	assert( td->kind == TypeData::Symbolic );
-	NamedTypeDecl * ret;
+	ast::NamedTypeDecl * ret;
 	assert( td->base );
 	if ( td->symbolic.isTypedef ) {
-		ret = new TypedefDecl( name, td->location, scs, typebuild( td->base ), linkage );
+		ret = new ast::TypedefDecl(
+			td->location,
+			name,
+			scs,
+			typebuild( td->base ),
+			linkage
+		);
 	} else {
-		ret = new TypeDecl( name, scs, typebuild( td->base ), TypeDecl::Dtype, true );
+		ret = new ast::TypeDecl(
+			td->location,
+			name,
+			scs,
+			typebuild( td->base ),
+			ast::TypeDecl::Dtype,
+			true
+		);
 	} // if
-	buildList( td->symbolic.assertions, ret->get_assertions() );
-	ret->base->attributes.splice( ret->base->attributes.end(), attributes );
+	buildList( td->symbolic.assertions, ret->assertions );
+	splice( ret->base.get_and_mutate()->attributes, attributes );
 	return ret;
 } // buildSymbolic
 
 
-EnumDecl * buildEnum( const TypeData * td, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ) {
+ast::EnumDecl * buildEnum(
+		const TypeData * td,
+		std::vector<ast::ptr<ast::Attribute>> && attributes,
+		ast::Linkage::Spec linkage ) {
 	assert( td->kind == TypeData::Enum );
-	Type * baseType = td->base ? typebuild(td->base) : nullptr;
-	EnumDecl * ret = new EnumDecl( *td->enumeration.name, attributes, td->enumeration.typed, linkage, baseType );
-	buildList( td->enumeration.constants, ret->get_members() );
-	list< Declaration * >::iterator members = ret->get_members().begin();
-	ret->hide = td->enumeration.hiding == EnumHiding::Hide ? EnumDecl::EnumHiding::Hide : EnumDecl::EnumHiding::Visible;
+	ast::Type * baseType = td->base ? typebuild(td->base) : nullptr;
+	ast::EnumDecl * ret = new ast::EnumDecl(
+		td->location,
+		*td->enumeration.name,
+		td->enumeration.typed,
+		std::move( attributes ),
+		linkage,
+		baseType
+	);
+	buildList( td->enumeration.constants, ret->members );
+	auto members = ret->members.begin();
+	ret->hide = td->enumeration.hiding == EnumHiding::Hide ? ast::EnumDecl::EnumHiding::Hide : ast::EnumDecl::EnumHiding::Visible;
 	for ( const DeclarationNode * cur = td->enumeration.constants; cur != nullptr; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ), ++members ) {
 		if ( cur->enumInLine ) {
@@ -900,8 +1268,13 @@
 			SemanticError( td->location, "Enumerator of enum(void) cannot have an explicit initializer value." );
 		} else if ( cur->has_enumeratorValue() ) {
-			ObjectDecl * member = dynamic_cast< ObjectDecl * >(* members);
-			member->set_init( new SingleInit( maybeMoveBuild( cur->consume_enumeratorValue() ) ) );
+			ast::Decl * member = members->get_and_mutate();
+			ast::ObjectDecl * object = strict_dynamic_cast<ast::ObjectDecl *>( member );
+			object->init = new ast::SingleInit(
+				td->location,
+				maybeMoveBuild( cur->consume_enumeratorValue() ),
+				ast::NoConstruct
+			);
 		} else if ( !cur->initializer ) {
-			if ( baseType && (!dynamic_cast<BasicType *>(baseType) || !dynamic_cast<BasicType *>(baseType)->isInteger())) {
+			if ( baseType && (!dynamic_cast<ast::BasicType *>(baseType) || !dynamic_cast<ast::BasicType *>(baseType)->isInteger())) {
 				SemanticError( td->location, "Enumerators of an non-integer typed enum must be explicitly initialized." );
 			}
@@ -910,43 +1283,138 @@
 		// if
 	} // for
-	ret->set_body( td->enumeration.body );
+	ret->body = td->enumeration.body;
 	return ret;
 } // buildEnum
 
 
-TypeInstType * buildSymbolicInst( const TypeData * td ) {
+ast::TypeInstType * buildSymbolicInst( const TypeData * td ) {
 	assert( td->kind == TypeData::SymbolicInst );
-	TypeInstType * ret = new TypeInstType( buildQualifiers( td ), *td->symbolic.name, false );
-	buildList( td->symbolic.actuals, ret->get_parameters() );
-	buildForall( td->forall, ret->get_forall() );
+	ast::TypeInstType * ret = new ast::TypeInstType(
+		*td->symbolic.name,
+		ast::TypeDecl::Dtype,
+		buildQualifiers( td )
+	);
+	buildList( td->symbolic.actuals, ret->params );
 	return ret;
 } // buildSymbolicInst
 
 
-TupleType * buildTuple( const TypeData * td ) {
+ast::TupleType * buildTuple( const TypeData * td ) {
 	assert( td->kind == TypeData::Tuple );
-	std::list< Type * > types;
+	std::vector<ast::ptr<ast::Type>> types;
 	buildTypeList( td->tuple, types );
-	TupleType * ret = new TupleType( buildQualifiers( td ), types );
-	buildForall( td->forall, ret->get_forall() );
+	ast::TupleType * ret = new ast::TupleType(
+		std::move( types ),
+		buildQualifiers( td )
+	);
 	return ret;
 } // buildTuple
 
 
-TypeofType * buildTypeof( const TypeData * td ) {
+ast::TypeofType * buildTypeof( const TypeData * td ) {
 	assert( td->kind == TypeData::Typeof || td->kind == TypeData::Basetypeof );
 	assert( td->typeexpr );
-	// assert( td->typeexpr->expr );
-	return new TypeofType{ buildQualifiers( td ), td->typeexpr->build(), td->kind == TypeData::Basetypeof };
+	return new ast::TypeofType(
+		td->typeexpr->build(),
+		td->kind == TypeData::Typeof
+			? ast::TypeofType::Typeof : ast::TypeofType::Basetypeof,
+		buildQualifiers( td )
+	);
 } // buildTypeof
 
 
-VTableType * buildVtable( const TypeData * td ) {
+ast::VTableType * buildVtable( const TypeData * td ) {
 	assert( td->base );
-	return new VTableType{ buildQualifiers( td ), typebuild( td->base ) };
+	return new ast::VTableType(
+		typebuild( td->base ),
+		buildQualifiers( td )
+	);
 } // buildVtable
 
 
-Declaration * buildDecl( const TypeData * td, const string &name, Type::StorageClasses scs, Expression * bitfieldWidth, Type::FuncSpecifiers funcSpec, LinkageSpec::Spec linkage, Expression *asmName, Initializer * init, std::list< Attribute * > attributes ) {
+ast::FunctionDecl * buildFunctionDecl(
+		const TypeData * td,
+		const string &name,
+		ast::Storage::Classes scs,
+		ast::Function::Specs funcSpec,
+		ast::Linkage::Spec linkage,
+		ast::Expr * asmName,
+		std::vector<ast::ptr<ast::Attribute>> && attributes ) {
+	assert( td->kind == TypeData::Function );
+	// For some reason FunctionDecl takes a bool instead of an ArgumentFlag.
+	bool isVarArgs = !td->function.params || td->function.params->hasEllipsis;
+	ast::CV::Qualifiers cvq = buildQualifiers( td );
+	std::vector<ast::ptr<ast::TypeDecl>> forall;
+	std::vector<ast::ptr<ast::DeclWithType>> assertions;
+	std::vector<ast::ptr<ast::DeclWithType>> params;
+	std::vector<ast::ptr<ast::DeclWithType>> returns;
+	buildList( td->function.params, params );
+	buildForall( td->forall, forall );
+	// Functions do not store their assertions there anymore.
+	for ( ast::ptr<ast::TypeDecl> & type_param : forall ) {
+		auto mut = type_param.get_and_mutate();
+		splice( assertions, mut->assertions );
+	}
+	if ( td->base ) {
+		switch ( td->base->kind ) {
+		case TypeData::Tuple:
+			buildList( td->base->tuple, returns );
+			break;
+		default:
+			returns.push_back( dynamic_cast<ast::DeclWithType *>(
+				buildDecl(
+					td->base,
+					"",
+					ast::Storage::Classes(),
+					(ast::Expr *)nullptr, // bitfieldWidth
+					ast::Function::Specs(),
+					ast::Linkage::Cforall,
+					(ast::Expr *)nullptr // asmName
+				)
+			) );
+		} // switch
+	} else {
+		returns.push_back( new ast::ObjectDecl(
+			td->location,
+			"",
+			new ast::BasicType( ast::BasicType::SignedInt ),
+			(ast::Init *)nullptr,
+			ast::Storage::Classes(),
+			ast::Linkage::Cforall
+		) );
+	} // if
+	ast::Stmt * stmt = maybeBuild( td->function.body );
+	ast::CompoundStmt * body = dynamic_cast<ast::CompoundStmt *>( stmt );
+	ast::FunctionDecl * decl = new ast::FunctionDecl( td->location,
+		name,
+		std::move( forall ),
+		std::move( assertions ),
+		std::move( params ),
+		std::move( returns ),
+		body,
+		scs,
+		linkage,
+		std::move( attributes ),
+		funcSpec,
+		isVarArgs
+	);
+	buildList( td->function.withExprs, decl->withExprs );
+	decl->asmName = asmName;
+	// This may be redundant on a declaration.
+	decl->type.get_and_mutate()->qualifiers = cvq;
+	return decl;
+} // buildFunctionDecl
+
+
+ast::Decl * buildDecl(
+		const TypeData * td,
+		const string &name,
+		ast::Storage::Classes scs,
+		ast::Expr * bitfieldWidth,
+		ast::Function::Specs funcSpec,
+		ast::Linkage::Spec linkage,
+		ast::Expr * asmName,
+		ast::Init * init,
+		std::vector<ast::ptr<ast::Attribute>> && attributes ) {
 	if ( td->kind == TypeData::Function ) {
 		if ( td->function.idList ) {					// KR function ?
@@ -954,18 +1422,25 @@
 		} // if
 
-		FunctionDecl * decl;
-		Statement * stmt = maybeBuild( td->function.body );
-		CompoundStmt * body = dynamic_cast< CompoundStmt * >( stmt );
-		decl = new FunctionDecl( name, scs, linkage, buildFunction( td ), body, attributes, funcSpec );
-		buildList( td->function.withExprs, decl->withExprs );
-		return decl->set_asmName( asmName );
+		return buildFunctionDecl(
+			td, name, scs, funcSpec, linkage,
+			asmName, std::move( attributes ) );
 	} else if ( td->kind == TypeData::Aggregate ) {
-		return buildAggregate( td, attributes, linkage );
+		return buildAggregate( td, std::move( attributes ), linkage );
 	} else if ( td->kind == TypeData::Enum ) {
-		return buildEnum( td, attributes, linkage );
+		return buildEnum( td, std::move( attributes ), linkage );
 	} else if ( td->kind == TypeData::Symbolic ) {
-		return buildSymbolic( td, attributes, name, scs, linkage );
+		return buildSymbolic( td, std::move( attributes ), name, scs, linkage );
 	} else {
-		return (new ObjectDecl( name, scs, linkage, bitfieldWidth, typebuild( td ), init, attributes ))->set_asmName( asmName );
+		auto ret = new ast::ObjectDecl( td->location,
+			name,
+			typebuild( td ),
+			init,
+			scs,
+			linkage,
+			bitfieldWidth,
+			std::move( attributes )
+		);
+		ret->asmName = asmName;
+		return ret;
 	} // if
 	return nullptr;
@@ -973,22 +1448,28 @@
 
 
-FunctionType * buildFunction( const TypeData * td ) {
+ast::FunctionType * buildFunctionType( const TypeData * td ) {
 	assert( td->kind == TypeData::Function );
-	FunctionType * ft = new FunctionType( buildQualifiers( td ), ! td->function.params || td->function.params->hasEllipsis );
-	buildList( td->function.params, ft->parameters );
+	ast::FunctionType * ft = new ast::FunctionType(
+		( !td->function.params || td->function.params->hasEllipsis )
+			? ast::VariableArgs : ast::FixedArgs,
+		buildQualifiers( td )
+	);
+	buildTypeList( td->function.params, ft->params );
 	buildForall( td->forall, ft->forall );
 	if ( td->base ) {
 		switch ( td->base->kind ) {
 		case TypeData::Tuple:
-			buildList( td->base->tuple, ft->returnVals );
+			buildTypeList( td->base->tuple, ft->returns );
 			break;
 		default:
-			ft->get_returnVals().push_back( dynamic_cast< DeclarationWithType * >( buildDecl( td->base, "", Type::StorageClasses(), nullptr, Type::FuncSpecifiers(), LinkageSpec::Cforall, nullptr ) ) );
+			ft->returns.push_back( typebuild( td->base ) );
+			break;
 		} // switch
 	} else {
-		ft->get_returnVals().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), nullptr ) );
+		ft->returns.push_back(
+			new ast::BasicType( ast::BasicType::SignedInt ) );
 	} // if
 	return ft;
-} // buildFunction
+} // buildFunctionType
 
 
@@ -1021,5 +1502,6 @@
 				param->type = decl->type;				// set copy declaration type to parameter type
 				decl->type = nullptr;					// reset declaration type
-				param->attributes.splice( param->attributes.end(), decl->attributes ); // copy and reset attributes from declaration to parameter
+				// Copy and reset attributes from declaration to parameter:
+				splice( param->attributes, decl->attributes );
 			} // if
 		} // for
Index: src/Parser/TypeData.h
===================================================================
--- src/Parser/TypeData.h	(revision 70056edafe6b115773f5da41e81a7b2adf5c08f5)
+++ src/Parser/TypeData.h	(revision e02e13fc53b4a6d659a7753b2c843a4b7e203c0d)
@@ -9,7 +9,7 @@
 // Author           : Peter A. Buhr
 // Created On       : Sat May 16 15:18:36 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Feb 24 14:25:02 2023
-// Update Count     : 205
+// Last Modified By : Andrew Beach
+// Last Modified On : Wed Mar  1 10:44:00 2023
+// Update Count     : 206
 //
 
@@ -20,8 +20,6 @@
 #include <string>										// for string
 
+#include "AST/Type.hpp"									// for Type
 #include "ParseNode.h"									// for DeclarationNode, DeclarationNode::Ag...
-#include "SynTree/LinkageSpec.h"						// for Spec
-#include "SynTree/Type.h"								// for Type, ReferenceToType (ptr only)
-#include "SynTree/SynTree.h"							// for Visitor Nodes
 
 struct TypeData {
@@ -30,5 +28,5 @@
 
 	struct Aggregate_t {
-		AggregateDecl::Aggregate kind;
+		ast::AggregateDecl::Aggregate kind;
 		const std::string * name = nullptr;
 		DeclarationNode * params = nullptr;
@@ -41,5 +39,5 @@
 	};
 
-	struct AggInst_t {									// handles SUE
+	struct AggInst_t {
 		TypeData * aggregate = nullptr;
 		ExpressionNode * params = nullptr;
@@ -93,5 +91,5 @@
 	DeclarationNode::BuiltinType builtintype = DeclarationNode::NoBuiltinType;
 
-	Type::Qualifiers qualifiers;
+	ast::CV::Qualifiers qualifiers;
 	DeclarationNode * forall = nullptr;
 
@@ -114,26 +112,26 @@
 };
 
-Type * typebuild( const TypeData * );
+ast::Type * typebuild( const TypeData * );
 TypeData * typeextractAggregate( const TypeData * td, bool toplevel = true );
-Type::Qualifiers buildQualifiers( const TypeData * td );
-Type * buildBasicType( const TypeData * );
-PointerType * buildPointer( const TypeData * );
-ArrayType * buildArray( const TypeData * );
-ReferenceType * buildReference( const TypeData * );
-AggregateDecl * buildAggregate( const TypeData *, std::list< Attribute * > );
-ReferenceToType * buildComAggInst( const TypeData *, std::list< Attribute * > attributes, LinkageSpec::Spec linkage );
-ReferenceToType * buildAggInst( const TypeData * );
-TypeDecl * buildVariable( const TypeData * );
-EnumDecl * buildEnum( const TypeData *, std::list< Attribute * >, LinkageSpec::Spec );
-TypeInstType * buildSymbolicInst( const TypeData * );
-TupleType * buildTuple( const TypeData * );
-TypeofType * buildTypeof( const TypeData * );
-VTableType * buildVtable( const TypeData * );
-Declaration * buildDecl(
-	const TypeData *, const std::string &, Type::StorageClasses, Expression *,
-	Type::FuncSpecifiers funcSpec, LinkageSpec::Spec, Expression * asmName,
-	Initializer * init = nullptr, std::list< class Attribute * > attributes = std::list< class Attribute * >() );
-FunctionType * buildFunction( const TypeData * );
-Declaration * addEnumBase( Declaration *, const TypeData * );
+ast::CV::Qualifiers buildQualifiers( const TypeData * td );
+ast::Type * buildBasicType( const TypeData * );
+ast::PointerType * buildPointer( const TypeData * );
+ast::ArrayType * buildArray( const TypeData * );
+ast::ReferenceType * buildReference( const TypeData * );
+ast::AggregateDecl * buildAggregate( const TypeData *, std::vector<ast::ptr<ast::Attribute>> );
+ast::BaseInstType * buildComAggInst( const TypeData *, std::vector<ast::ptr<ast::Attribute>> && attributes, ast::Linkage::Spec linkage );
+ast::BaseInstType * buildAggInst( const TypeData * );
+ast::TypeDecl * buildVariable( const TypeData * );
+ast::EnumDecl * buildEnum( const TypeData *, std::vector<ast::ptr<ast::Attribute>> &&, ast::Linkage::Spec );
+ast::TypeInstType * buildSymbolicInst( const TypeData * );
+ast::TupleType * buildTuple( const TypeData * );
+ast::TypeofType * buildTypeof( const TypeData * );
+ast::VTableType * buildVtable( const TypeData * );
+ast::Decl * buildDecl(
+	const TypeData *, const std::string &, ast::Storage::Classes, ast::Expr *,
+	ast::Function::Specs funcSpec, ast::Linkage::Spec, ast::Expr * asmName,
+	ast::Init * init = nullptr, std::vector<ast::ptr<ast::Attribute>> && attributes = std::vector<ast::ptr<ast::Attribute>>() );
+ast::FunctionType * buildFunctionType( const TypeData * );
+ast::Decl * addEnumBase( Declaration *, const TypeData * );
 void buildKRFunction( const TypeData::Function_t & function );
 
Index: src/Parser/lex.ll
===================================================================
--- src/Parser/lex.ll	(revision 70056edafe6b115773f5da41e81a7b2adf5c08f5)
+++ src/Parser/lex.ll	(revision e02e13fc53b4a6d659a7753b2c843a4b7e203c0d)
@@ -23,5 +23,5 @@
 // line-number directives) and C/C++ style comments, which are ignored.
 
-//**************************** Includes and Defines ****************************
+// *************************** Includes and Defines ****************************
 
 #ifdef __clang__
Index: src/Parser/parser.yy
===================================================================
--- src/Parser/parser.yy	(revision 70056edafe6b115773f5da41e81a7b2adf5c08f5)
+++ src/Parser/parser.yy	(revision e02e13fc53b4a6d659a7753b2c843a4b7e203c0d)
@@ -9,7 +9,7 @@
 // Author           : Peter A. Buhr
 // Created On       : Sat Sep  1 20:22:55 2001
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Mar 30 21:28:25 2023
-// Update Count     : 6328
+// Last Modified By : Andrew Beach
+// Last Modified On : Tue Apr  4 14:02:00 2023
+// Update Count     : 6329
 //
 
@@ -64,8 +64,8 @@
 
 extern DeclarationNode * parseTree;
-extern LinkageSpec::Spec linkage;
+extern ast::Linkage::Spec linkage;
 extern TypedefTable typedefTable;
 
-stack<LinkageSpec::Spec> linkageStack;
+stack<ast::Linkage::Spec> linkageStack;
 
 bool appendStr( string & to, string & from ) {
@@ -200,6 +200,6 @@
 } // fieldDecl
 
-#define NEW_ZERO new ExpressionNode( build_constantInteger( *new string( "0" ) ) )
-#define NEW_ONE  new ExpressionNode( build_constantInteger( *new string( "1" ) ) )
+#define NEW_ZERO new ExpressionNode( build_constantInteger( yylloc, *new string( "0" ) ) )
+#define NEW_ONE  new ExpressionNode( build_constantInteger( yylloc, *new string( "1" ) ) )
 #define UPDOWN( compop, left, right ) (compop == OperKinds::LThan || compop == OperKinds::LEThan ? left : right)
 #define MISSING_ANON_FIELD "Missing loop fields with an anonymous loop index is meaningless as loop index is unavailable in loop body."
@@ -208,4 +208,5 @@
 
 static ForCtrl * makeForCtrl(
+		const CodeLocation & location,
 		DeclarationNode * init,
 		enum OperKinds compop,
@@ -213,12 +214,12 @@
 		ExpressionNode * inc ) {
 	// Wrap both comp/inc if they are non-null.
-	if ( comp ) comp = new ExpressionNode( build_binary_val(
+	if ( comp ) comp = new ExpressionNode( build_binary_val( location,
 		compop,
-		new ExpressionNode( build_varref( new string( *init->name ) ) ),
+		new ExpressionNode( build_varref( location, new string( *init->name ) ) ),
 		comp ) );
-	if ( inc ) inc = new ExpressionNode( build_binary_val(
+	if ( inc ) inc = new ExpressionNode( build_binary_val( location,
 		// choose += or -= for upto/downto
 		compop == OperKinds::LThan || compop == OperKinds::LEThan ? OperKinds::PlusAssn : OperKinds::MinusAssn,
-		new ExpressionNode( build_varref( new string( *init->name ) ) ),
+		new ExpressionNode( build_varref( location, new string( *init->name ) ) ),
 		inc ) );
 	// The StatementNode call frees init->name, it must happen later.
@@ -226,5 +227,5 @@
 }
 
-ForCtrl * forCtrl( DeclarationNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
+ForCtrl * forCtrl( const CodeLocation & location, DeclarationNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
 	if ( index->initializer ) {
 		SemanticError( yylloc, "Direct initialization disallowed. Use instead: type var; initialization ~ comparison ~ increment." );
@@ -234,11 +235,11 @@
 	} // if
 	DeclarationNode * initDecl = index->addInitializer( new InitializerNode( start ) );
-	return makeForCtrl( initDecl, compop, comp, inc );
+	return makeForCtrl( location, initDecl, compop, comp, inc );
 } // forCtrl
 
-ForCtrl * forCtrl( ExpressionNode * type, string * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
-	ConstantExpr * constant = dynamic_cast<ConstantExpr *>(type->expr.get());
-	if ( constant && (constant->get_constant()->get_value() == "0" || constant->get_constant()->get_value() == "1") ) {
-		type = new ExpressionNode( new CastExpr( maybeMoveBuild( type ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) ) );
+ForCtrl * forCtrl( const CodeLocation & location, ExpressionNode * type, string * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
+	ast::ConstantExpr * constant = dynamic_cast<ast::ConstantExpr *>(type->expr.get());
+	if ( constant && (constant->rep == "0" || constant->rep == "1") ) {
+		type = new ExpressionNode( new ast::CastExpr( location, maybeMoveBuild(type), new ast::BasicType( ast::BasicType::SignedInt ) ) );
 	} // if
 	DeclarationNode * initDecl = distAttr(
@@ -246,13 +247,13 @@
 		DeclarationNode::newName( index )->addInitializer( new InitializerNode( start ) )
 	);
-	return makeForCtrl( initDecl, compop, comp, inc );
+	return makeForCtrl( location, initDecl, compop, comp, inc );
 } // forCtrl
 
-ForCtrl * forCtrl( ExpressionNode * type, ExpressionNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
-	if ( NameExpr * identifier = dynamic_cast<NameExpr *>(index->expr.get()) ) {
-		return forCtrl( type, new string( identifier->name ), start, compop, comp, inc );
-	} else if ( CommaExpr * commaExpr = dynamic_cast<CommaExpr *>(index->expr.get()) ) {
-		if ( NameExpr * identifier = dynamic_cast<NameExpr *>(commaExpr->arg1 ) ) {
-			return forCtrl( type, new string( identifier->name ), start, compop, comp, inc );
+ForCtrl * forCtrl( const CodeLocation & location, ExpressionNode * type, ExpressionNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
+	if ( auto identifier = dynamic_cast<ast::NameExpr *>(index->expr.get()) ) {
+		return forCtrl( location, type, new string( identifier->name ), start, compop, comp, inc );
+	} else if ( auto commaExpr = dynamic_cast<ast::CommaExpr *>( index->expr.get() ) ) {
+		if ( auto identifier = commaExpr->arg1.as<ast::NameExpr>() ) {
+			return forCtrl( location, type, new string( identifier->name ), start, compop, comp, inc );
 		} else {
 			SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed." ); return nullptr;
@@ -299,9 +300,9 @@
 	ExpressionNode * en;
 	DeclarationNode * decl;
-	AggregateDecl::Aggregate aggKey;
-	TypeDecl::Kind tclass;
+	ast::AggregateDecl::Aggregate aggKey;
+	ast::TypeDecl::Kind tclass;
 	StatementNode * sn;
-	WaitForStmt * wfs;
-	Expression * constant;
+	ast::WaitForStmt * wfs;
+	ast::Expr * constant;
 	CondCtl * ifctl;
 	ForCtrl * fctl;
@@ -313,9 +314,9 @@
 	bool flag;
 	EnumHiding hide;
-	CatchStmt::Kind catch_kind;
-	GenericExpr * genexpr;
+	ast::ExceptionKind catch_kind;
+	ast::GenericExpr * genexpr;
 }
 
-//************************* TERMINAL TOKENS ********************************
+// ************************ TERMINAL TOKENS ********************************
 
 // keywords
@@ -611,9 +612,9 @@
 constant:
 		// ENUMERATIONconstant is not included here; it is treated as a variable with type "enumeration constant".
-	INTEGERconstant								{ $$ = new ExpressionNode( build_constantInteger( *$1 ) ); }
-	| FLOATING_DECIMALconstant					{ $$ = new ExpressionNode( build_constantFloat( *$1 ) ); }
-	| FLOATING_FRACTIONconstant					{ $$ = new ExpressionNode( build_constantFloat( *$1 ) ); }
-	| FLOATINGconstant							{ $$ = new ExpressionNode( build_constantFloat( *$1 ) ); }
-	| CHARACTERconstant							{ $$ = new ExpressionNode( build_constantChar( *$1 ) ); }
+	INTEGERconstant								{ $$ = new ExpressionNode( build_constantInteger( yylloc, *$1 ) ); }
+	| FLOATING_DECIMALconstant					{ $$ = new ExpressionNode( build_constantFloat( yylloc, *$1 ) ); }
+	| FLOATING_FRACTIONconstant					{ $$ = new ExpressionNode( build_constantFloat( yylloc, *$1 ) ); }
+	| FLOATINGconstant							{ $$ = new ExpressionNode( build_constantFloat( yylloc, *$1 ) ); }
+	| CHARACTERconstant							{ $$ = new ExpressionNode( build_constantChar( yylloc, *$1 ) ); }
 	;
 
@@ -641,5 +642,5 @@
 
 string_literal:
-	string_literal_list							{ $$ = build_constantStr( *$1 ); }
+	string_literal_list							{ $$ = build_constantStr( yylloc, *$1 ); }
 	;
 
@@ -658,18 +659,18 @@
 primary_expression:
 	IDENTIFIER											// typedef name cannot be used as a variable name
-		{ $$ = new ExpressionNode( build_varref( $1 ) ); }
+		{ $$ = new ExpressionNode( build_varref( yylloc, $1 ) ); }
 	| quasi_keyword
-		{ $$ = new ExpressionNode( build_varref( $1 ) ); }
+		{ $$ = new ExpressionNode( build_varref( yylloc, $1 ) ); }
 	| TYPEDIMname										// CFA, generic length argument
 		// { $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( DeclarationNode::newFromTypedef( $1 ) ) ) ); }
 		// { $$ = new ExpressionNode( build_varref( $1 ) ); }
-		{ $$ = new ExpressionNode( build_dimensionref( $1 ) ); }
+		{ $$ = new ExpressionNode( build_dimensionref( yylloc, $1 ) ); }
 	| tuple
 	| '(' comma_expression ')'
 		{ $$ = $2; }
 	| '(' compound_statement ')'						// GCC, lambda expression
-		{ $$ = new ExpressionNode( new StmtExpr( dynamic_cast<CompoundStmt *>(maybeMoveBuild( $2 ) ) ) ); }
+		{ $$ = new ExpressionNode( new ast::StmtExpr( yylloc, dynamic_cast<ast::CompoundStmt *>( maybeMoveBuild( $2 ) ) ) ); }
 	| type_name '.' identifier							// CFA, nested type
-		{ $$ = new ExpressionNode( build_qualified_expr( $1, build_varref( $3 ) ) ); }
+		{ $$ = new ExpressionNode( build_qualified_expr( yylloc, $1, build_varref( yylloc, $3 ) ) ); }
 	| type_name '.' '[' field_name_list ']'				// CFA, nested type / tuple field selector
 		{ SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
@@ -703,5 +704,6 @@
 		{
 			// steal the association node from the singleton and delete the wrapper
-			$1->associations.splice($1->associations.end(), $3->associations);
+			assert( 1 == $3->associations.size() );
+			$1->associations.push_back( $3->associations.front() );
 			delete $3;
 			$$ = $1;
@@ -713,8 +715,8 @@
 		{
 			// create a GenericExpr wrapper with one association pair
-			$$ = new GenericExpr( nullptr, { { maybeMoveBuildType($1), maybeMoveBuild( $3 ) } } );
+			$$ = new ast::GenericExpr( yylloc, nullptr, { { maybeMoveBuildType( $1 ), maybeMoveBuild( $3 ) } } );
 		}
 	| DEFAULT ':' assignment_expression
-		{ $$ = new GenericExpr( nullptr, { { maybeMoveBuild( $3 ) } } ); }
+		{ $$ = new ast::GenericExpr( yylloc, nullptr, { { maybeMoveBuild( $3 ) } } ); }
 	;
 
@@ -725,5 +727,5 @@
 		// Switching to this behaviour may help check if a C compatibilty case uses comma-exprs in subscripts.
 		// Current: Commas in subscripts make tuples.
-		{ $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, new ExpressionNode( build_tuple( (ExpressionNode *)($3->set_last( $5 ) ) )) ) ); }
+		{ $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, new ExpressionNode( build_tuple( yylloc, (ExpressionNode *)($3->set_last( $5 ) ) )) ) ); }
 	| postfix_expression '[' assignment_expression ']'
 		// CFA, comma_expression disallowed in this context because it results in a common user error: subscripting a
@@ -731,56 +733,56 @@
 		// little advantage to this feature and many disadvantages. It is possible to write x[(i,j)] in CFA, which is
 		// equivalent to the old x[i,j].
-		{ $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, $3 ) ); }
+		{ $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, $3 ) ); }
 	| constant '[' assignment_expression ']'			// 3[a], 'a'[a], 3.5[a]
-		{ $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, $3 ) ); }
+		{ $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, $3 ) ); }
 	| string_literal '[' assignment_expression ']'		// "abc"[3], 3["abc"]
-		{ $$ = new ExpressionNode( build_binary_val( OperKinds::Index, new ExpressionNode( $1 ), $3 ) ); }
+		{ $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, new ExpressionNode( $1 ), $3 ) ); }
 	| postfix_expression '{' argument_expression_list_opt '}' // CFA, constructor call
 		{
 			Token fn;
 			fn.str = new std::string( "?{}" );			// location undefined - use location of '{'?
-			$$ = new ExpressionNode( new ConstructorExpr( build_func( new ExpressionNode( build_varref( fn ) ), (ExpressionNode *)( $1 )->set_last( $3 ) ) ) );
+			$$ = new ExpressionNode( new ast::ConstructorExpr( yylloc, build_func( yylloc, new ExpressionNode( build_varref( yylloc, fn ) ), (ExpressionNode *)( $1 )->set_last( $3 ) ) ) );
 		}
 	| postfix_expression '(' argument_expression_list_opt ')'
-		{ $$ = new ExpressionNode( build_func( $1, $3 ) ); }
+		{ $$ = new ExpressionNode( build_func( yylloc, $1, $3 ) ); }
 	| VA_ARG '(' primary_expression ',' declaration_specifier_nobody abstract_parameter_declarator_opt ')'
 		// { SemanticError( yylloc, "va_arg is currently unimplemented." ); $$ = nullptr; }
-		{ $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( new string( "__builtin_va_arg") ) ),
+		{ $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, new string( "__builtin_va_arg") ) ),
 											   (ExpressionNode *)($3->set_last( (ExpressionNode *)($6 ? $6->addType( $5 ) : $5) )) ) ); }
 	| postfix_expression '`' identifier					// CFA, postfix call
-		{ $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( build_postfix_name( $3 ) ) ), $1 ) ); }
+		{ $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), $1 ) ); }
 	| constant '`' identifier							// CFA, postfix call
-		{ $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( build_postfix_name( $3 ) ) ), $1 ) ); }
+		{ $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), $1 ) ); }
 	| string_literal '`' identifier						// CFA, postfix call
-		{ $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( build_postfix_name( $3 ) ) ), new ExpressionNode( $1 ) ) ); }
+		{ $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), new ExpressionNode( $1 ) ) ); }
 	| postfix_expression '.' identifier
-		{ $$ = new ExpressionNode( build_fieldSel( $1, build_varref( $3 ) ) ); }
+		{ $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_varref( yylloc, $3 ) ) ); }
 	| postfix_expression '.' INTEGERconstant			// CFA, tuple index
-		{ $$ = new ExpressionNode( build_fieldSel( $1, build_constantInteger( *$3 ) ) ); }
+		{ $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_constantInteger( yylloc, *$3 ) ) ); }
 	| postfix_expression FLOATING_FRACTIONconstant		// CFA, tuple index
-		{ $$ = new ExpressionNode( build_fieldSel( $1, build_field_name_FLOATING_FRACTIONconstant( *$2 ) ) ); }
+		{ $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_field_name_FLOATING_FRACTIONconstant( yylloc, *$2 ) ) ); }
 	| postfix_expression '.' '[' field_name_list ']'	// CFA, tuple field selector
-		{ $$ = new ExpressionNode( build_fieldSel( $1, build_tuple( $4 ) ) ); }
+		{ $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); }
 	| postfix_expression '.' aggregate_control
-		{ $$ = new ExpressionNode( build_keyword_cast( $3, $1 ) ); }
+		{ $$ = new ExpressionNode( build_keyword_cast( yylloc, $3, $1 ) ); }
 	| postfix_expression ARROW identifier
-		{ $$ = new ExpressionNode( build_pfieldSel( $1, build_varref( $3 ) ) ); }
+		{ $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_varref( yylloc, $3 ) ) ); }
 	| postfix_expression ARROW INTEGERconstant			// CFA, tuple index
-		{ $$ = new ExpressionNode( build_pfieldSel( $1, build_constantInteger( *$3 ) ) ); }
+		{ $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_constantInteger( yylloc, *$3 ) ) ); }
 	| postfix_expression ARROW '[' field_name_list ']'	// CFA, tuple field selector
-		{ $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple( $4 ) ) ); }
+		{ $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); }
 	| postfix_expression ICR
-		{ $$ = new ExpressionNode( build_unary_val( OperKinds::IncrPost, $1 ) ); }
+		{ $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::IncrPost, $1 ) ); }
 	| postfix_expression DECR
-		{ $$ = new ExpressionNode( build_unary_val( OperKinds::DecrPost, $1 ) ); }
+		{ $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::DecrPost, $1 ) ); }
 	| '(' type_no_function ')' '{' initializer_list_opt comma_opt '}' // C99, compound-literal
-		{ $$ = new ExpressionNode( build_compoundLiteral( $2, new InitializerNode( $5, true ) ) ); }
+		{ $$ = new ExpressionNode( build_compoundLiteral( yylloc, $2, new InitializerNode( $5, true ) ) ); }
 	| '(' type_no_function ')' '@' '{' initializer_list_opt comma_opt '}' // CFA, explicit C compound-literal
-		{ $$ = new ExpressionNode( build_compoundLiteral( $2, (new InitializerNode( $6, true ))->set_maybeConstructed( false ) ) ); }
+		{ $$ = new ExpressionNode( build_compoundLiteral( yylloc, $2, (new InitializerNode( $6, true ))->set_maybeConstructed( false ) ) ); }
 	| '^' primary_expression '{' argument_expression_list_opt '}' // CFA, destructor call
 		{
 			Token fn;
 			fn.str = new string( "^?{}" );				// location undefined
-			$$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( fn ) ), (ExpressionNode *)( $2 )->set_last( $4 ) ) );
+			$$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, fn ) ), (ExpressionNode *)( $2 )->set_last( $4 ) ) );
 		}
 	;
@@ -813,25 +815,25 @@
 	field_name
 	| FLOATING_DECIMALconstant field
-		{ $$ = new ExpressionNode( build_fieldSel( new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( *$1 ) ), maybeMoveBuild( $2 ) ) ); }
+		{ $$ = new ExpressionNode( build_fieldSel( yylloc, new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( yylloc, *$1 ) ), maybeMoveBuild( $2 ) ) ); }
 	| FLOATING_DECIMALconstant '[' field_name_list ']'
-		{ $$ = new ExpressionNode( build_fieldSel( new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( *$1 ) ), build_tuple( $3 ) ) ); }
+		{ $$ = new ExpressionNode( build_fieldSel( yylloc, new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( yylloc, *$1 ) ), build_tuple( yylloc, $3 ) ) ); }
 	| field_name '.' field
-		{ $$ = new ExpressionNode( build_fieldSel( $1, maybeMoveBuild( $3 ) ) ); }
+		{ $$ = new ExpressionNode( build_fieldSel( yylloc, $1, maybeMoveBuild( $3 ) ) ); }
 	| field_name '.' '[' field_name_list ']'
-		{ $$ = new ExpressionNode( build_fieldSel( $1, build_tuple( $4 ) ) ); }
+		{ $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); }
 	| field_name ARROW field
-		{ $$ = new ExpressionNode( build_pfieldSel( $1, maybeMoveBuild( $3 ) ) ); }
+		{ $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, maybeMoveBuild( $3 ) ) ); }
 	| field_name ARROW '[' field_name_list ']'
-		{ $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple( $4 ) ) ); }
+		{ $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); }
 	;
 
 field_name:
 	INTEGERconstant	fraction_constants_opt
-		{ $$ = new ExpressionNode( build_field_name_fraction_constants( build_constantInteger( *$1 ), $2 ) ); }
+		{ $$ = new ExpressionNode( build_field_name_fraction_constants( yylloc, build_constantInteger( yylloc, *$1 ), $2 ) ); }
 	| FLOATINGconstant fraction_constants_opt
-		{ $$ = new ExpressionNode( build_field_name_fraction_constants( build_field_name_FLOATINGconstant( *$1 ), $2 ) ); }
+		{ $$ = new ExpressionNode( build_field_name_fraction_constants( yylloc, build_field_name_FLOATINGconstant( yylloc, *$1 ), $2 ) ); }
 	| identifier_at fraction_constants_opt				// CFA, allow anonymous fields
 		{
-			$$ = new ExpressionNode( build_field_name_fraction_constants( build_varref( $1 ), $2 ) );
+			$$ = new ExpressionNode( build_field_name_fraction_constants( yylloc, build_varref( yylloc, $1 ), $2 ) );
 		}
 	;
@@ -842,6 +844,6 @@
 	| fraction_constants_opt FLOATING_FRACTIONconstant
 		{
-			Expression * constant = build_field_name_FLOATING_FRACTIONconstant( *$2 );
-			$$ = $1 != nullptr ? new ExpressionNode( build_fieldSel( $1,  constant ) ) : new ExpressionNode( constant );
+			ast::Expr * constant = build_field_name_FLOATING_FRACTIONconstant( yylloc, *$2 );
+			$$ = $1 != nullptr ? new ExpressionNode( build_fieldSel( yylloc, $1, constant ) ) : new ExpressionNode( constant );
 		}
 	;
@@ -862,33 +864,33 @@
 		{
 			switch ( $1 ) {
-			  case OperKinds::AddressOf:
-				$$ = new ExpressionNode( new AddressExpr( maybeMoveBuild( $2 ) ) );
+			case OperKinds::AddressOf:
+				$$ = new ExpressionNode( new ast::AddressExpr( maybeMoveBuild( $2 ) ) );
 				break;
-			  case OperKinds::PointTo:
-				$$ = new ExpressionNode( build_unary_val( $1, $2 ) );
+			case OperKinds::PointTo:
+				$$ = new ExpressionNode( build_unary_val( yylloc, $1, $2 ) );
 				break;
-			  case OperKinds::And:
-				$$ = new ExpressionNode( new AddressExpr( new AddressExpr( maybeMoveBuild( $2 ) ) ) );
+			case OperKinds::And:
+				$$ = new ExpressionNode( new ast::AddressExpr( new ast::AddressExpr( maybeMoveBuild( $2 ) ) ) );
 				break;
-			  default:
+			default:
 				assert( false );
 			}
 		}
 	| unary_operator cast_expression
-		{ $$ = new ExpressionNode( build_unary_val( $1, $2 ) ); }
+		{ $$ = new ExpressionNode( build_unary_val( yylloc, $1, $2 ) ); }
 	| ICR unary_expression
-		{ $$ = new ExpressionNode( build_unary_val( OperKinds::Incr, $2 ) ); }
+		{ $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::Incr, $2 ) ); }
 	| DECR unary_expression
-		{ $$ = new ExpressionNode( build_unary_val( OperKinds::Decr, $2 ) ); }
+		{ $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::Decr, $2 ) ); }
 	| SIZEOF unary_expression
-		{ $$ = new ExpressionNode( new SizeofExpr( maybeMoveBuild( $2 ) ) ); }
+		{ $$ = new ExpressionNode( new ast::SizeofExpr( yylloc, maybeMoveBuild( $2 ) ) ); }
 	| SIZEOF '(' type_no_function ')'
-		{ $$ = new ExpressionNode( new SizeofExpr( maybeMoveBuildType( $3 ) ) ); }
+		{ $$ = new ExpressionNode( new ast::SizeofExpr( yylloc, maybeMoveBuildType( $3 ) ) ); }
 	| ALIGNOF unary_expression							// GCC, variable alignment
-		{ $$ = new ExpressionNode( new AlignofExpr( maybeMoveBuild( $2 ) ) ); }
+		{ $$ = new ExpressionNode( new ast::AlignofExpr( yylloc, maybeMoveBuild( $2 ) ) ); }
 	| ALIGNOF '(' type_no_function ')'					// GCC, type alignment
-		{ $$ = new ExpressionNode( new AlignofExpr( maybeMoveBuildType( $3 ) ) ); }
+		{ $$ = new ExpressionNode( new ast::AlignofExpr( yylloc, maybeMoveBuildType( $3 ) ) ); }
 	| OFFSETOF '(' type_no_function ',' identifier ')'
-		{ $$ = new ExpressionNode( build_offsetOf( $3, build_varref( $5 ) ) ); }
+		{ $$ = new ExpressionNode( build_offsetOf( yylloc, $3, build_varref( yylloc, $5 ) ) ); }
 	| TYPEID '(' type_no_function ')'
 		{
@@ -915,13 +917,13 @@
 	unary_expression
 	| '(' type_no_function ')' cast_expression
-		{ $$ = new ExpressionNode( build_cast( $2, $4 ) ); }
+		{ $$ = new ExpressionNode( build_cast( yylloc, $2, $4 ) ); }
 	| '(' aggregate_control '&' ')' cast_expression		// CFA
-		{ $$ = new ExpressionNode( build_keyword_cast( $2, $5 ) ); }
+		{ $$ = new ExpressionNode( build_keyword_cast( yylloc, $2, $5 ) ); }
 	| '(' aggregate_control '*' ')' cast_expression		// CFA
-		{ $$ = new ExpressionNode( build_keyword_cast( $2, $5 ) ); }
+		{ $$ = new ExpressionNode( build_keyword_cast( yylloc, $2, $5 ) ); }
 	| '(' VIRTUAL ')' cast_expression					// CFA
-		{ $$ = new ExpressionNode( new VirtualCastExpr( maybeMoveBuild( $4 ), maybeMoveBuildType( nullptr ) ) ); }
+		{ $$ = new ExpressionNode( new ast::VirtualCastExpr( yylloc, maybeMoveBuild( $4 ), maybeMoveBuildType( nullptr ) ) ); }
 	| '(' VIRTUAL type_no_function ')' cast_expression	// CFA
-		{ $$ = new ExpressionNode( new VirtualCastExpr( maybeMoveBuild( $5 ), maybeMoveBuildType( $3 ) ) ); }
+		{ $$ = new ExpressionNode( new ast::VirtualCastExpr( yylloc, maybeMoveBuild( $5 ), maybeMoveBuildType( $3 ) ) ); }
 	| '(' RETURN type_no_function ')' cast_expression	// CFA
 		{ SemanticError( yylloc, "Return cast is currently unimplemented." ); $$ = nullptr; }
@@ -931,5 +933,5 @@
 		{ SemanticError( yylloc, "Qualifier cast is currently unimplemented." ); $$ = nullptr; }
 //	| '(' type_no_function ')' tuple
-//		{ $$ = new ExpressionNode( build_cast( $2, $4 ) ); }
+//		{ $$ = new ast::ExpressionNode( build_cast( yylloc, $2, $4 ) ); }
 	;
 
@@ -949,5 +951,5 @@
 	cast_expression
 	| exponential_expression '\\' cast_expression
-		{ $$ = new ExpressionNode( build_binary_val( OperKinds::Exp, $1, $3 ) ); }
+		{ $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Exp, $1, $3 ) ); }
 	;
 
@@ -955,9 +957,9 @@
 	exponential_expression
 	| multiplicative_expression '*' exponential_expression
-		{ $$ = new ExpressionNode( build_binary_val( OperKinds::Mul, $1, $3 ) ); }
+		{ $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Mul, $1, $3 ) ); }
 	| multiplicative_expression '/' exponential_expression
-		{ $$ = new ExpressionNode( build_binary_val( OperKinds::Div, $1, $3 ) ); }
+		{ $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Div, $1, $3 ) ); }
 	| multiplicative_expression '%' exponential_expression
-		{ $$ = new ExpressionNode( build_binary_val( OperKinds::Mod, $1, $3 ) ); }
+		{ $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Mod, $1, $3 ) ); }
 	;
 
@@ -965,7 +967,7 @@
 	multiplicative_expression
 	| additive_expression '+' multiplicative_expression
-		{ $$ = new ExpressionNode( build_binary_val( OperKinds::Plus, $1, $3 ) ); }
+		{ $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Plus, $1, $3 ) ); }
 	| additive_expression '-' multiplicative_expression
-		{ $$ = new ExpressionNode( build_binary_val( OperKinds::Minus, $1, $3 ) ); }
+		{ $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Minus, $1, $3 ) ); }
 	;
 
@@ -973,7 +975,7 @@
 	additive_expression
 	| shift_expression LS additive_expression
-		{ $$ = new ExpressionNode( build_binary_val( OperKinds::LShift, $1, $3 ) ); }
+		{ $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::LShift, $1, $3 ) ); }
 	| shift_expression RS additive_expression
-		{ $$ = new ExpressionNode( build_binary_val( OperKinds::RShift, $1, $3 ) ); }
+		{ $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::RShift, $1, $3 ) ); }
 	;
 
@@ -981,11 +983,11 @@
 	shift_expression
 	| relational_expression '<' shift_expression
-		{ $$ = new ExpressionNode( build_binary_val( OperKinds::LThan, $1, $3 ) ); }
+		{ $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::LThan, $1, $3 ) ); }
 	| relational_expression '>' shift_expression
-		{ $$ = new ExpressionNode( build_binary_val( OperKinds::GThan, $1, $3 ) ); }
+		{ $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::GThan, $1, $3 ) ); }
 	| relational_expression LE shift_expression
-		{ $$ = new ExpressionNode( build_binary_val( OperKinds::LEThan, $1, $3 ) ); }
+		{ $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::LEThan, $1, $3 ) ); }
 	| relational_expression GE shift_expression
-		{ $$ = new ExpressionNode( build_binary_val( OperKinds::GEThan, $1, $3 ) ); }
+		{ $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::GEThan, $1, $3 ) ); }
 	;
 
@@ -993,7 +995,7 @@
 	relational_expression
 	| equality_expression EQ relational_expression
-		{ $$ = new ExpressionNode( build_binary_val( OperKinds::Eq, $1, $3 ) ); }
+		{ $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Eq, $1, $3 ) ); }
 	| equality_expression NE relational_expression
-		{ $$ = new ExpressionNode( build_binary_val( OperKinds::Neq, $1, $3 ) ); }
+		{ $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Neq, $1, $3 ) ); }
 	;
 
@@ -1001,5 +1003,5 @@
 	equality_expression
 	| AND_expression '&' equality_expression
-		{ $$ = new ExpressionNode( build_binary_val( OperKinds::BitAnd, $1, $3 ) ); }
+		{ $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::BitAnd, $1, $3 ) ); }
 	;
 
@@ -1007,5 +1009,5 @@
 	AND_expression
 	| exclusive_OR_expression '^' AND_expression
-		{ $$ = new ExpressionNode( build_binary_val( OperKinds::Xor, $1, $3 ) ); }
+		{ $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Xor, $1, $3 ) ); }
 	;
 
@@ -1013,5 +1015,5 @@
 	exclusive_OR_expression
 	| inclusive_OR_expression '|' exclusive_OR_expression
-		{ $$ = new ExpressionNode( build_binary_val( OperKinds::BitOr, $1, $3 ) ); }
+		{ $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::BitOr, $1, $3 ) ); }
 	;
 
@@ -1019,5 +1021,5 @@
 	inclusive_OR_expression
 	| logical_AND_expression ANDAND inclusive_OR_expression
-		{ $$ = new ExpressionNode( build_and_or( $1, $3, true ) ); }
+		{ $$ = new ExpressionNode( build_and_or( yylloc, $1, $3, ast::AndExpr ) ); }
 	;
 
@@ -1025,5 +1027,5 @@
 	logical_AND_expression
 	| logical_OR_expression OROR logical_AND_expression
-		{ $$ = new ExpressionNode( build_and_or( $1, $3, false ) ); }
+		{ $$ = new ExpressionNode( build_and_or( yylloc, $1, $3, ast::OrExpr ) ); }
 	;
 
@@ -1031,8 +1033,8 @@
 	logical_OR_expression
 	| logical_OR_expression '?' comma_expression ':' conditional_expression
-		{ $$ = new ExpressionNode( build_cond( $1, $3, $5 ) ); }
+		{ $$ = new ExpressionNode( build_cond( yylloc, $1, $3, $5 ) ); }
 		// FIX ME: computes $1 twice
 	| logical_OR_expression '?' /* empty */ ':' conditional_expression // GCC, omitted first operand
-		{ $$ = new ExpressionNode( build_cond( $1, $1, $4 ) ); }
+		{ $$ = new ExpressionNode( build_cond( yylloc, $1, $1, $4 ) ); }
 	;
 
@@ -1049,5 +1051,5 @@
 //				SemanticError( yylloc, "C @= assignment is currently unimplemented." ); $$ = nullptr;
 //			} else {
-				$$ = new ExpressionNode( build_binary_val( $2, $1, $3 ) );
+				$$ = new ExpressionNode( build_binary_val( yylloc, $2, $1, $3 ) );
 //			} // if
 		}
@@ -1094,7 +1096,7 @@
 //		{ $$ = new ExpressionNode( build_tuple( $3 ) ); }
 	'[' ',' tuple_expression_list ']'
-		{ $$ = new ExpressionNode( build_tuple( (ExpressionNode *)(new ExpressionNode( nullptr ) )->set_last( $3 ) ) ); }
+		{ $$ = new ExpressionNode( build_tuple( yylloc, (ExpressionNode *)(new ExpressionNode( nullptr ) )->set_last( $3 ) ) ); }
 	| '[' push assignment_expression pop ',' tuple_expression_list ']'
-		{ $$ = new ExpressionNode( build_tuple( (ExpressionNode *)($3->set_last( $6 ) ) )); }
+		{ $$ = new ExpressionNode( build_tuple( yylloc, (ExpressionNode *)($3->set_last( $6 ) ) )); }
 	;
 
@@ -1112,5 +1114,5 @@
 	assignment_expression
 	| comma_expression ',' assignment_expression
-		{ $$ = new ExpressionNode( new CommaExpr( maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }
+		{ $$ = new ExpressionNode( new ast::CommaExpr( yylloc, maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }
 	;
 
@@ -1139,5 +1141,5 @@
 	| asm_statement
 	| DIRECTIVE
-		{ $$ = new StatementNode( build_directive( $1 ) ); }
+		{ $$ = new StatementNode( build_directive( yylloc, $1 ) ); }
 	;
 
@@ -1145,5 +1147,5 @@
 		// labels cannot be identifiers 0 or 1
 	identifier_or_type_name ':' attribute_list_opt statement
-		{ $$ = $4->add_label( $1, $3 ); }
+		{ $$ = $4->add_label( yylloc, $1, $3 ); }
 	| identifier_or_type_name ':' attribute_list_opt error // syntax error
 		{
@@ -1157,10 +1159,10 @@
 compound_statement:
 	'{' '}'
-		{ $$ = new StatementNode( build_compound( (StatementNode *)0 ) ); }
+		{ $$ = new StatementNode( build_compound( yylloc, (StatementNode *)0 ) ); }
 	| '{' push
 	  local_label_declaration_opt						// GCC, local labels appear at start of block
 	  statement_decl_list								// C99, intermix declarations and statements
 	  pop '}'
-		{ $$ = new StatementNode( build_compound( $4 ) ); }
+		{ $$ = new StatementNode( build_compound( yylloc, $4 ) ); }
 	;
 
@@ -1193,5 +1195,5 @@
 expression_statement:
 	comma_expression_opt ';'
-		{ $$ = new StatementNode( build_expr( $1 ) ); }
+		{ $$ = new StatementNode( build_expr( yylloc, $1 ) ); }
 	;
 
@@ -1202,8 +1204,8 @@
 		{ $$ = $2; }
 	| SWITCH '(' comma_expression ')' case_clause
-		{ $$ = new StatementNode( build_switch( true, $3, $5 ) ); }
+		{ $$ = new StatementNode( build_switch( yylloc, true, $3, $5 ) ); }
 	| SWITCH '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt pop '}' // CFA
 		{
-			StatementNode *sw = new StatementNode( build_switch( true, $3, $8 ) );
+			StatementNode *sw = new StatementNode( build_switch( yylloc, true, $3, $8 ) );
 			// The semantics of the declaration list is changed to include associated initialization, which is performed
 			// *before* the transfer to the appropriate case clause by hoisting the declarations into a compound
@@ -1211,14 +1213,14 @@
 			// therefore, are removed from the grammar even though C allows it. The change also applies to choose
 			// statement.
-			$$ = $7 ? new StatementNode( build_compound( (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;
+			$$ = $7 ? new StatementNode( build_compound( yylloc, (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;
 		}
 	| SWITCH '(' comma_expression ')' '{' error '}'		// CFA, syntax error
 		{ SemanticError( yylloc, "Only declarations can appear before the list of case clauses." ); $$ = nullptr; }
 	| CHOOSE '(' comma_expression ')' case_clause		// CFA
-		{ $$ = new StatementNode( build_switch( false, $3, $5 ) ); }
+		{ $$ = new StatementNode( build_switch( yylloc, false, $3, $5 ) ); }
 	| CHOOSE '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt pop '}' // CFA
 		{
-			StatementNode *sw = new StatementNode( build_switch( false, $3, $8 ) );
-			$$ = $7 ? new StatementNode( build_compound( (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;
+			StatementNode *sw = new StatementNode( build_switch( yylloc, false, $3, $8 ) );
+			$$ = $7 ? new StatementNode( build_compound( yylloc, (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;
 		}
 	| CHOOSE '(' comma_expression ')' '{' error '}'		// CFA, syntax error
@@ -1229,7 +1231,7 @@
 	IF '(' conditional_declaration ')' statement		%prec THEN
 		// explicitly deal with the shift/reduce conflict on if/else
-		{ $$ = new StatementNode( build_if( $3, maybe_build_compound( $5 ), nullptr ) ); }
+		{ $$ = new StatementNode( build_if( yylloc, $3, maybe_build_compound( yylloc, $5 ), nullptr ) ); }
 	| IF '(' conditional_declaration ')' statement ELSE statement
-		{ $$ = new StatementNode( build_if( $3, maybe_build_compound( $5 ), maybe_build_compound( $7 ) ) ); }
+		{ $$ = new StatementNode( build_if( yylloc, $3, maybe_build_compound( yylloc, $5 ), maybe_build_compound( yylloc, $7 ) ) ); }
 	;
 
@@ -1251,5 +1253,5 @@
 	constant_expression							{ $$ = $1; }
 	| constant_expression ELLIPSIS constant_expression	// GCC, subrange
-		{ $$ = new ExpressionNode( new RangeExpr( maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }
+		{ $$ = new ExpressionNode( new ast::RangeExpr( yylloc, maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }
 	| subrange											// CFA, subrange
 	;
@@ -1267,5 +1269,5 @@
 	| CASE case_value_list error						// syntax error
 		{ SemanticError( yylloc, "Missing colon after case list." ); $$ = nullptr; }
-	| DEFAULT ':'								{ $$ = new StatementNode( build_default() ); }
+	| DEFAULT ':'								{ $$ = new StatementNode( build_default( yylloc ) ); }
 		// A semantic check is required to ensure only one default clause per switch/choose statement.
 	| DEFAULT error										//  syntax error
@@ -1279,5 +1281,5 @@
 
 case_clause:											// CFA
-	case_label_list statement					{ $$ = $1->append_last_case( maybe_build_compound( $2 ) ); }
+	case_label_list statement					{ $$ = $1->append_last_case( maybe_build_compound( yylloc, $2 ) ); }
 	;
 
@@ -1290,43 +1292,43 @@
 switch_clause_list:										// CFA
 	case_label_list statement_list_nodecl
-		{ $$ = $1->append_last_case( new StatementNode( build_compound( $2 ) ) ); }
+		{ $$ = $1->append_last_case( new StatementNode( build_compound( yylloc, $2 ) ) ); }
 	| switch_clause_list case_label_list statement_list_nodecl
-		{ $$ = (StatementNode *)( $1->set_last( $2->append_last_case( new StatementNode( build_compound( $3 ) ) ) ) ); }
+		{ $$ = (StatementNode *)( $1->set_last( $2->append_last_case( new StatementNode( build_compound( yylloc, $3 ) ) ) ) ); }
 	;
 
 iteration_statement:
 	WHILE '(' ')' statement								%prec THEN // CFA => while ( 1 )
-		{ $$ = new StatementNode( build_while( new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( $4 ) ) ); }
+		{ $$ = new StatementNode( build_while( yylloc, new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( yylloc, $4 ) ) ); }
 	| WHILE '(' ')' statement ELSE statement			// CFA
 		{
-			$$ = new StatementNode( build_while( new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( $4 ) ) );
+			$$ = new StatementNode( build_while( yylloc, new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( yylloc, $4 ) ) );
 			SemanticWarning( yylloc, Warning::SuperfluousElse );
 		}
 	| WHILE '(' conditional_declaration ')' statement	%prec THEN
-		{ $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ) ) ); }
+		{ $$ = new StatementNode( build_while( yylloc, $3, maybe_build_compound( yylloc, $5 ) ) ); }
 	| WHILE '(' conditional_declaration ')' statement ELSE statement // CFA
-		{ $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ), $7 ) ); }
+		{ $$ = new StatementNode( build_while( yylloc, $3, maybe_build_compound( yylloc, $5 ), $7 ) ); }
 	| DO statement WHILE '(' ')' ';'					// CFA => do while( 1 )
-		{ $$ = new StatementNode( build_do_while( NEW_ONE, maybe_build_compound( $2 ) ) ); }
+		{ $$ = new StatementNode( build_do_while( yylloc, NEW_ONE, maybe_build_compound( yylloc, $2 ) ) ); }
 	| DO statement WHILE '(' ')' ELSE statement			// CFA
 		{
-			$$ = new StatementNode( build_do_while( NEW_ONE, maybe_build_compound( $2 ) ) );
+			$$ = new StatementNode( build_do_while( yylloc, NEW_ONE, maybe_build_compound( yylloc, $2 ) ) );
 			SemanticWarning( yylloc, Warning::SuperfluousElse );
 		}
 	| DO statement WHILE '(' comma_expression ')' ';'
-		{ $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ) ) ); }
+		{ $$ = new StatementNode( build_do_while( yylloc, $5, maybe_build_compound( yylloc, $2 ) ) ); }
 	| DO statement WHILE '(' comma_expression ')' ELSE statement // CFA
-		{ $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ), $8 ) ); }
+		{ $$ = new StatementNode( build_do_while( yylloc, $5, maybe_build_compound( yylloc, $2 ), $8 ) ); }
 	| FOR '(' ')' statement								%prec THEN // CFA => for ( ;; )
-		{ $$ = new StatementNode( build_for( new ForCtrl( nullptr, nullptr, nullptr ), maybe_build_compound( $4 ) ) ); }
+		{ $$ = new StatementNode( build_for( yylloc, new ForCtrl( nullptr, nullptr, nullptr ), maybe_build_compound( yylloc, $4 ) ) ); }
 	| FOR '(' ')' statement ELSE statement				// CFA
 		{
-			$$ = new StatementNode( build_for( new ForCtrl( nullptr, nullptr, nullptr ), maybe_build_compound( $4 ) ) );
+			$$ = new StatementNode( build_for( yylloc, new ForCtrl( nullptr, nullptr, nullptr ), maybe_build_compound( yylloc, $4 ) ) );
 			SemanticWarning( yylloc, Warning::SuperfluousElse );
 		}
 	| FOR '(' for_control_expression_list ')' statement	%prec THEN
-		{ $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ) ) ); }
+		{ $$ = new StatementNode( build_for( yylloc, $3, maybe_build_compound( yylloc, $5 ) ) ); }
 	| FOR '(' for_control_expression_list ')' statement ELSE statement // CFA
-		{ $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ), $7 ) ); }
+		{ $$ = new StatementNode( build_for( yylloc, $3, maybe_build_compound( yylloc, $5 ), $7 ) ); }
 	;
 
@@ -1342,10 +1344,10 @@
 			if ( $1->condition ) {
 				if ( $3->condition ) {
-					$1->condition->expr.reset( new LogicalExpr( $1->condition->expr.release(), $3->condition->expr.release(), true ) );
+					$1->condition->expr.reset( new ast::LogicalExpr( yylloc, $1->condition->expr.release(), $3->condition->expr.release(), ast::AndExpr ) );
 				} // if
 			} else $1->condition = $3->condition;
 			if ( $1->change ) {
 				if ( $3->change ) {
-					$1->change->expr.reset( new CommaExpr( $1->change->expr.release(), $3->change->expr.release() ) );
+					$1->change->expr.reset( new ast::CommaExpr( yylloc, $1->change->expr.release(), $3->change->expr.release() ) );
 				} // if
 			} else $1->change = $3->change;
@@ -1359,5 +1361,5 @@
 	| comma_expression ';' comma_expression_opt ';' comma_expression_opt
 		{
-			StatementNode * init = $1 ? new StatementNode( new ExprStmt( maybeMoveBuild( $1 ) ) ) : nullptr;
+			StatementNode * init = $1 ? new StatementNode( new ast::ExprStmt( yylloc, maybeMoveBuild( $1 ) ) ) : nullptr;
 			$$ = new ForCtrl( init, $3, $5 );
 		}
@@ -1371,14 +1373,14 @@
 
 	| comma_expression									// CFA, anonymous loop-index
-		{ $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), NEW_ZERO, OperKinds::LThan, $1->clone(), NEW_ONE ); }
+		{ $$ = forCtrl( yylloc, $1, new string( DeclarationNode::anonymous.newName() ), NEW_ZERO, OperKinds::LThan, $1->clone(), NEW_ONE ); }
 	| downupdowneq comma_expression						// CFA, anonymous loop-index
-		{ $$ = forCtrl( $2, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $1, NEW_ZERO, $2->clone() ), $1, UPDOWN( $1, $2->clone(), NEW_ZERO ), NEW_ONE ); }
+		{ $$ = forCtrl( yylloc, $2, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $1, NEW_ZERO, $2->clone() ), $1, UPDOWN( $1, $2->clone(), NEW_ZERO ), NEW_ONE ); }
 
 	| comma_expression updowneq comma_expression		// CFA, anonymous loop-index
-		{ $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), NEW_ONE ); }
+		{ $$ = forCtrl( yylloc, $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), NEW_ONE ); }
 	| '@' updowneq comma_expression						// CFA, anonymous loop-index
 		{
 			if ( $2 == OperKinds::LThan || $2 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
-			else $$ = forCtrl( $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, NEW_ONE );
+			else $$ = forCtrl( yylloc, $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, NEW_ONE );
 		}
 	| comma_expression updowneq '@'						// CFA, anonymous loop-index
@@ -1388,9 +1390,9 @@
 		}
 	| comma_expression updowneq comma_expression '~' comma_expression // CFA, anonymous loop-index
-		{ $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), $5 ); }
+		{ $$ = forCtrl( yylloc, $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), $5 ); }
 	| '@' updowneq comma_expression '~' comma_expression // CFA, anonymous loop-index
 		{
 			if ( $2 == OperKinds::LThan || $2 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
-			else $$ = forCtrl( $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, $5 );
+			else $$ = forCtrl( yylloc, $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, $5 );
 		}
 	| comma_expression updowneq '@' '~' comma_expression // CFA, anonymous loop-index
@@ -1411,14 +1413,14 @@
 
 	| comma_expression ';' comma_expression				// CFA
-		{ $$ = forCtrl( $3, $1, NEW_ZERO, OperKinds::LThan, $3->clone(), NEW_ONE ); }
+		{ $$ = forCtrl( yylloc, $3, $1, NEW_ZERO, OperKinds::LThan, $3->clone(), NEW_ONE ); }
 	| comma_expression ';' downupdowneq comma_expression // CFA
-		{ $$ = forCtrl( $4, $1, UPDOWN( $3, NEW_ZERO, $4->clone() ), $3, UPDOWN( $3, $4->clone(), NEW_ZERO ), NEW_ONE ); }
+		{ $$ = forCtrl( yylloc, $4, $1, UPDOWN( $3, NEW_ZERO, $4->clone() ), $3, UPDOWN( $3, $4->clone(), NEW_ZERO ), NEW_ONE ); }
 
 	| comma_expression ';' comma_expression updowneq comma_expression // CFA
-		{ $$ = forCtrl( $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), NEW_ONE ); }
+		{ $$ = forCtrl( yylloc, $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), NEW_ONE ); }
 	| comma_expression ';' '@' updowneq comma_expression // CFA
 		{
 			if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
-			else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, NEW_ONE );
+			else $$ = forCtrl( yylloc, $5, $1, $5->clone(), $4, nullptr, NEW_ONE );
 		}
 	| comma_expression ';' comma_expression updowneq '@' // CFA
@@ -1426,5 +1428,5 @@
 			if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
 			else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
-			else $$ = forCtrl( $3, $1, $3->clone(), $4, nullptr, NEW_ONE );
+			else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, NEW_ONE );
 		}
 	| comma_expression ';' '@' updowneq '@'				// CFA, error
@@ -1432,9 +1434,9 @@
 
 	| comma_expression ';' comma_expression updowneq comma_expression '~' comma_expression // CFA
-		{ $$ = forCtrl( $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), $7 ); }
+		{ $$ = forCtrl( yylloc, $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), $7 ); }
 	| comma_expression ';' '@' updowneq comma_expression '~' comma_expression // CFA, error
 		{
 			if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
-			else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, $7 );
+			else $$ = forCtrl( yylloc, $5, $1, $5->clone(), $4, nullptr, $7 );
 		}
 	| comma_expression ';' comma_expression updowneq '@' '~' comma_expression // CFA
@@ -1442,12 +1444,12 @@
 			if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
 			else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
-			else $$ = forCtrl( $3, $1, $3->clone(), $4, nullptr, $7 );
+			else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, $7 );
 		}
 	| comma_expression ';' comma_expression updowneq comma_expression '~' '@' // CFA
-		{ $$ = forCtrl( $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), nullptr ); }
+		{ $$ = forCtrl( yylloc, $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), nullptr ); }
 	| comma_expression ';' '@' updowneq comma_expression '~' '@' // CFA, error
 		{
 			if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
-			else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, nullptr );
+			else $$ = forCtrl( yylloc, $5, $1, $5->clone(), $4, nullptr, nullptr );
 		}
 	| comma_expression ';' comma_expression updowneq '@' '~' '@' // CFA
@@ -1455,5 +1457,5 @@
 			if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
 			else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
-			else $$ = forCtrl( $3, $1, $3->clone(), $4, nullptr, nullptr );
+			else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, nullptr );
 		}
 	| comma_expression ';' '@' updowneq '@' '~' '@' // CFA
@@ -1461,14 +1463,14 @@
 
 	| declaration comma_expression						// CFA
-		{ $$ = forCtrl( $1, NEW_ZERO, OperKinds::LThan, $2, NEW_ONE ); }
+		{ $$ = forCtrl( yylloc, $1, NEW_ZERO, OperKinds::LThan, $2, NEW_ONE ); }
 	| declaration downupdowneq comma_expression			// CFA
-		{ $$ = forCtrl( $1, UPDOWN( $2, NEW_ZERO, $3 ), $2, UPDOWN( $2, $3->clone(), NEW_ZERO ), NEW_ONE ); }
+		{ $$ = forCtrl( yylloc, $1, UPDOWN( $2, NEW_ZERO, $3 ), $2, UPDOWN( $2, $3->clone(), NEW_ZERO ), NEW_ONE ); }
 
 	| declaration comma_expression updowneq comma_expression // CFA
-		{ $$ = forCtrl( $1, UPDOWN( $3, $2->clone(), $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), NEW_ONE ); }
+		{ $$ = forCtrl( yylloc, $1, UPDOWN( $3, $2->clone(), $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), NEW_ONE ); }
 	| declaration '@' updowneq comma_expression			// CFA
 		{
 			if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
-			else $$ = forCtrl( $1, $4, $3, nullptr, NEW_ONE );
+			else $$ = forCtrl( yylloc, $1, $4, $3, nullptr, NEW_ONE );
 		}
 	| declaration comma_expression updowneq '@'			// CFA
@@ -1476,13 +1478,13 @@
 			if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
 			else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
-			else $$ = forCtrl( $1, $2, $3, nullptr, NEW_ONE );
+			else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, NEW_ONE );
 		}
 
 	| declaration comma_expression updowneq comma_expression '~' comma_expression // CFA
-		{ $$ = forCtrl( $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), $6 ); }
+		{ $$ = forCtrl( yylloc, $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), $6 ); }
 	| declaration '@' updowneq comma_expression '~' comma_expression // CFA
 		{
 			if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
-			else $$ = forCtrl( $1, $4, $3, nullptr, $6 );
+			else $$ = forCtrl( yylloc, $1, $4, $3, nullptr, $6 );
 		}
 	| declaration comma_expression updowneq '@' '~' comma_expression // CFA
@@ -1490,12 +1492,12 @@
 			if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
 			else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
-			else $$ = forCtrl( $1, $2, $3, nullptr, $6 );
+			else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, $6 );
 		}
 	| declaration comma_expression updowneq comma_expression '~' '@' // CFA
-		{ $$ = forCtrl( $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), nullptr ); }
+		{ $$ = forCtrl( yylloc, $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), nullptr ); }
 	| declaration '@' updowneq comma_expression '~' '@' // CFA
 		{
 			if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
-			else $$ = forCtrl( $1, $4, $3, nullptr, nullptr );
+			else $$ = forCtrl( yylloc, $1, $4, $3, nullptr, nullptr );
 		}
 	| declaration comma_expression updowneq '@' '~' '@'	// CFA
@@ -1503,5 +1505,5 @@
 			if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
 			else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
-			else $$ = forCtrl( $1, $2, $3, nullptr, nullptr );
+			else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, nullptr );
 		}
 	| declaration '@' updowneq '@' '~' '@'				// CFA, error
@@ -1546,5 +1548,5 @@
 jump_statement:
 	GOTO identifier_or_type_name ';'
-		{ $$ = new StatementNode( build_branch( $2, BranchStmt::Goto ) ); }
+		{ $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::Goto ) ); }
 	| GOTO '*' comma_expression ';'						// GCC, computed goto
 		// The syntax for the GCC computed goto violates normal expression precedence, e.g., goto *i+3; => goto *(i+3);
@@ -1553,43 +1555,43 @@
 		// A semantic check is required to ensure fallthru appears only in the body of a choose statement.
 	| fall_through_name ';'								// CFA
-		{ $$ = new StatementNode( build_branch( BranchStmt::FallThrough ) ); }
+		{ $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::FallThrough ) ); }
 	| fall_through_name identifier_or_type_name ';'		// CFA
-		{ $$ = new StatementNode( build_branch( $2, BranchStmt::FallThrough ) ); }
+		{ $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::FallThrough ) ); }
 	| fall_through_name DEFAULT ';'						// CFA
-		{ $$ = new StatementNode( build_branch( BranchStmt::FallThroughDefault ) ); }
+		{ $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::FallThroughDefault ) ); }
 	| CONTINUE ';'
 		// A semantic check is required to ensure this statement appears only in the body of an iteration statement.
-		{ $$ = new StatementNode( build_branch( BranchStmt::Continue ) ); }
+		{ $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::Continue ) ); }
 	| CONTINUE identifier_or_type_name ';'				// CFA, multi-level continue
 		// A semantic check is required to ensure this statement appears only in the body of an iteration statement, and
 		// the target of the transfer appears only at the start of an iteration statement.
-		{ $$ = new StatementNode( build_branch( $2, BranchStmt::Continue ) ); }
+		{ $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::Continue ) ); }
 	| BREAK ';'
 		// A semantic check is required to ensure this statement appears only in the body of an iteration statement.
-		{ $$ = new StatementNode( build_branch( BranchStmt::Break ) ); }
+		{ $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::Break ) ); }
 	| BREAK identifier_or_type_name ';'					// CFA, multi-level exit
 		// A semantic check is required to ensure this statement appears only in the body of an iteration statement, and
 		// the target of the transfer appears only at the start of an iteration statement.
-		{ $$ = new StatementNode( build_branch( $2, BranchStmt::Break ) ); }
+		{ $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::Break ) ); }
 	| RETURN comma_expression_opt ';'
-		{ $$ = new StatementNode( build_return( $2 ) ); }
+		{ $$ = new StatementNode( build_return( yylloc, $2 ) ); }
 	| RETURN '{' initializer_list_opt comma_opt '}' ';'
 		{ SemanticError( yylloc, "Initializer return is currently unimplemented." ); $$ = nullptr; }
 	| SUSPEND ';'
-		{ $$ = new StatementNode( build_suspend( nullptr ) ); }
+		{ $$ = new StatementNode( build_suspend( yylloc, nullptr, ast::SuspendStmt::None ) ); }
 	| SUSPEND compound_statement
-		{ $$ = new StatementNode( build_suspend( $2 ) ); }
+		{ $$ = new StatementNode( build_suspend( yylloc, $2, ast::SuspendStmt::None ) ); }
 	| SUSPEND COROUTINE ';'
-		{ $$ = new StatementNode( build_suspend( nullptr, SuspendStmt::Coroutine ) ); }
+		{ $$ = new StatementNode( build_suspend( yylloc, nullptr, ast::SuspendStmt::Coroutine ) ); }
 	| SUSPEND COROUTINE compound_statement
-		{ $$ = new StatementNode( build_suspend( $3, SuspendStmt::Coroutine ) ); }
+		{ $$ = new StatementNode( build_suspend( yylloc, $3, ast::SuspendStmt::Coroutine ) ); }
 	| SUSPEND GENERATOR ';'
-		{ $$ = new StatementNode( build_suspend( nullptr, SuspendStmt::Generator ) ); }
+		{ $$ = new StatementNode( build_suspend( yylloc, nullptr, ast::SuspendStmt::Generator ) ); }
 	| SUSPEND GENERATOR compound_statement
-		{ $$ = new StatementNode( build_suspend( $3, SuspendStmt::Generator ) ); }
+		{ $$ = new StatementNode( build_suspend( yylloc, $3, ast::SuspendStmt::Generator ) ); }
 	| THROW assignment_expression_opt ';'				// handles rethrow
-		{ $$ = new StatementNode( build_throw( $2 ) ); }
+		{ $$ = new StatementNode( build_throw( yylloc, $2 ) ); }
 	| THROWRESUME assignment_expression_opt ';'			// handles reresume
-		{ $$ = new StatementNode( build_resume( $2 ) ); }
+		{ $$ = new StatementNode( build_resume( yylloc, $2 ) ); }
 	| THROWRESUME assignment_expression_opt AT assignment_expression ';' // handles reresume
 		{ $$ = new StatementNode( build_resume_at( $2, $4 ) ); }
@@ -1603,5 +1605,5 @@
 with_statement:
 	WITH '(' tuple_expression_list ')' statement
-		{ $$ = new StatementNode( build_with( $3, $5 ) ); }
+		{ $$ = new StatementNode( build_with( yylloc, $3, $5 ) ); }
 	;
 
@@ -1611,5 +1613,5 @@
 		{
 			if ( ! $3 ) { SemanticError( yylloc, "mutex argument list cannot be empty." ); $$ = nullptr; }
-			$$ = new StatementNode( build_mutex( $3, $5 ) );
+			$$ = new StatementNode( build_mutex( yylloc, $3, $5 ) );
 		}
 	;
@@ -1650,16 +1652,17 @@
 	when_clause_opt waitfor statement					%prec THEN
 		// Called first: create header for WaitForStmt.
-		{ $$ = build_waitfor( new WaitForStmt(), $1, $2, maybe_build_compound( $3 ) ); }
+		{ $$ = build_waitfor( yylloc, new ast::WaitForStmt( yylloc ), $1, $2, maybe_build_compound( yylloc, $3 ) ); }
 	| wor_waitfor_clause wor when_clause_opt waitfor statement
-		{ $$ = build_waitfor( $1, $3, $4, maybe_build_compound( $5 ) ); }
+		{ $$ = build_waitfor( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ); }
 	| wor_waitfor_clause wor when_clause_opt ELSE statement
-		{ $$ = build_waitfor_else( $1, $3, maybe_build_compound( $5 ) ); }
+		{ $$ = build_waitfor_else( yylloc, $1, $3, maybe_build_compound( yylloc, $5 ) ); }
 	| wor_waitfor_clause wor when_clause_opt timeout statement	%prec THEN
-		{ $$ = build_waitfor_timeout( $1, $3, $4, maybe_build_compound( $5 ) ); }
+		{ $$ = build_waitfor_timeout( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ); }
 	// "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless)
 	| wor_waitfor_clause wor when_clause_opt timeout statement wor ELSE statement // syntax error
 		{ SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; }
 	| wor_waitfor_clause wor when_clause_opt timeout statement wor when_clause ELSE statement
-		{ $$ = build_waitfor_else( build_waitfor_timeout( $1, $3, $4, maybe_build_compound( $5 ) ), $7, maybe_build_compound( $9 ) ); }
+		{ $$ = build_waitfor_else( yylloc, build_waitfor_timeout( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ), $7, maybe_build_compound( yylloc, $9 ) ); }
+	;
 
 waitfor_statement:
@@ -1711,21 +1714,21 @@
 	wor_waituntil_clause								%prec THEN
 		// SKULLDUGGERY: create an empty compound statement to test parsing of waituntil statement.
-		{ $$ = new StatementNode( build_compound( (StatementNode *)0 ) ); }
+		{ $$ = new StatementNode( build_compound( yylloc, nullptr ) ); }
 	;
 
 exception_statement:
-	TRY compound_statement handler_clause				%prec THEN
-		{ $$ = new StatementNode( build_try( $2, $3, nullptr ) ); }
+	TRY compound_statement handler_clause					%prec THEN
+		{ $$ = new StatementNode( build_try( yylloc, $2, $3, nullptr ) ); }
 	| TRY compound_statement finally_clause
-		{ $$ = new StatementNode( build_try( $2, nullptr, $3 ) ); }
+		{ $$ = new StatementNode( build_try( yylloc, $2, nullptr, $3 ) ); }
 	| TRY compound_statement handler_clause finally_clause
-		{ $$ = new StatementNode( build_try( $2, $3, $4 ) ); }
+		{ $$ = new StatementNode( build_try( yylloc, $2, $3, $4 ) ); }
 	;
 
 handler_clause:
 	handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement
-		{ $$ = new StatementNode( build_catch( $1, $4, $6, $8 ) ); }
+		{ $$ = new StatementNode( build_catch( yylloc, $1, $4, $6, $8 ) ); }
 	| handler_clause handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement
-		{ $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch( $2, $5, $7, $9 ) ) ); }
+		{ $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch( yylloc, $2, $5, $7, $9 ) ) ); }
 	;
 
@@ -1737,12 +1740,12 @@
 
 handler_key:
-	CATCH										{ $$ = CatchStmt::Terminate; }
-	| RECOVER									{ $$ = CatchStmt::Terminate; }
-	| CATCHRESUME								{ $$ = CatchStmt::Resume; }
-	| FIXUP										{ $$ = CatchStmt::Resume; }
+	CATCH										{ $$ = ast::Terminate; }
+	| RECOVER									{ $$ = ast::Terminate; }
+	| CATCHRESUME								{ $$ = ast::Resume; }
+	| FIXUP										{ $$ = ast::Resume; }
 	;
 
 finally_clause:
-	FINALLY compound_statement					{ $$ = new StatementNode( build_finally( $2 ) ); }
+	FINALLY compound_statement					{ $$ = new StatementNode( build_finally( yylloc, $2 ) ); }
 	;
 
@@ -1770,13 +1773,13 @@
 asm_statement:
 	ASM asm_volatile_opt '(' string_literal ')' ';'
-		{ $$ = new StatementNode( build_asm( $2, $4, nullptr ) ); }
+		{ $$ = new StatementNode( build_asm( yylloc, $2, $4, nullptr ) ); }
 	| ASM asm_volatile_opt '(' string_literal ':' asm_operands_opt ')' ';' // remaining GCC
-		{ $$ = new StatementNode( build_asm( $2, $4, $6 ) ); }
+		{ $$ = new StatementNode( build_asm( yylloc, $2, $4, $6 ) ); }
 	| ASM asm_volatile_opt '(' string_literal ':' asm_operands_opt ':' asm_operands_opt ')' ';'
-		{ $$ = new StatementNode( build_asm( $2, $4, $6, $8 ) ); }
+		{ $$ = new StatementNode( build_asm( yylloc, $2, $4, $6, $8 ) ); }
 	| ASM asm_volatile_opt '(' string_literal ':' asm_operands_opt ':' asm_operands_opt ':' asm_clobbers_list_opt ')' ';'
-		{ $$ = new StatementNode( build_asm( $2, $4, $6, $8, $10 ) ); }
+		{ $$ = new StatementNode( build_asm( yylloc, $2, $4, $6, $8, $10 ) ); }
 	| ASM asm_volatile_opt GOTO '(' string_literal ':' ':' asm_operands_opt ':' asm_clobbers_list_opt ':' label_list ')' ';'
-		{ $$ = new StatementNode( build_asm( $2, $5, nullptr, $8, $10, $12 ) ); }
+		{ $$ = new StatementNode( build_asm( yylloc, $2, $5, nullptr, $8, $10, $12 ) ); }
 	;
 
@@ -1802,7 +1805,10 @@
 asm_operand:											// GCC
 	string_literal '(' constant_expression ')'
-		{ $$ = new ExpressionNode( new AsmExpr( nullptr, $1, maybeMoveBuild( $3 ) ) ); }
+		{ $$ = new ExpressionNode( new ast::AsmExpr( yylloc, "", $1, maybeMoveBuild( $3 ) ) ); }
 	| '[' IDENTIFIER ']' string_literal '(' constant_expression ')'
-		{ $$ = new ExpressionNode( new AsmExpr( $2, $4, maybeMoveBuild( $6 ) ) ); }
+		{
+			$$ = new ExpressionNode( new ast::AsmExpr( yylloc, *$2.str, $4, maybeMoveBuild( $6 ) ) );
+			delete $2.str;
+		}
 	;
 
@@ -1819,10 +1825,10 @@
 	identifier
 		{
-			$$ = new LabelNode(); $$->labels.push_back( *$1 );
+			$$ = new LabelNode(); $$->labels.emplace_back( yylloc, *$1 );
 			delete $1;									// allocated by lexer
 		}
 	| label_list ',' identifier
 		{
-			$$ = $1; $1->labels.push_back( *$3 );
+			$$ = $1; $1->labels.emplace_back( yylloc, *$3 );
 			delete $3;									// allocated by lexer
 		}
@@ -1887,5 +1893,5 @@
 		{ $$ = DeclarationNode::newStaticAssert( $3, $5 ); }
 	| STATICASSERT '(' constant_expression ')' ';'		// CFA
-		{ $$ = DeclarationNode::newStaticAssert( $3, build_constantStr( *new string( "\"\"" ) ) ); }
+		{ $$ = DeclarationNode::newStaticAssert( $3, build_constantStr( yylloc, *new string( "\"\"" ) ) ); }
 
 // C declaration syntax is notoriously confusing and error prone. Cforall provides its own type, variable and function
@@ -2087,5 +2093,5 @@
 		{
 			SemanticError( yylloc, ::toString( "Missing ';' after end of ",
-				$1->type->enumeration.name ? "enum" : AggregateDecl::aggrString( $1->type->aggregate.kind ),
+				$1->type->enumeration.name ? "enum" : ast::AggregateDecl::aggrString( $1->type->aggregate.kind ),
 				" declaration" ) );
 			$$ = nullptr;
@@ -2321,5 +2327,5 @@
 		{ $$ = DeclarationNode::newTypeof( $3 ); }
 	| BASETYPEOF '(' type ')'							// CFA: basetypeof( x ) y;
-		{ $$ = DeclarationNode::newTypeof( new ExpressionNode( new TypeExpr( maybeMoveBuildType( $3 ) ) ), true ); }
+		{ $$ = DeclarationNode::newTypeof( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ), true ); }
 	| BASETYPEOF '(' comma_expression ')'				// CFA: basetypeof( a+b ) y;
 		{ $$ = DeclarationNode::newTypeof( $3, true ); }
@@ -2515,29 +2521,38 @@
 aggregate_data:
 	STRUCT vtable_opt
-		{ $$ = AggregateDecl::Struct; }
+		{ $$ = ast::AggregateDecl::Struct; }
 	| UNION
-		{ $$ = AggregateDecl::Union; }
+		{ $$ = ast::AggregateDecl::Union; }
 	| EXCEPTION											// CFA
-		{ $$ = AggregateDecl::Exception; }
-	  //		{ SemanticError( yylloc, "exception aggregate is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
+		{ $$ = ast::AggregateDecl::Exception; }
+	  //		{ SemanticError( yylloc, "exception aggregate is currently unimplemented." ); $$ = ast::AggregateDecl::NoAggregate; }
 	;
 
 aggregate_control:										// CFA
 	MONITOR
-		{ $$ = AggregateDecl::Monitor; }
+		{ $$ = ast::AggregateDecl::Monitor; }
 	| MUTEX STRUCT
-		{ $$ = AggregateDecl::Monitor; }
+		{ $$ = ast::AggregateDecl::Monitor; }
 	| GENERATOR
-		{ $$ = AggregateDecl::Generator; }
+		{ $$ = ast::AggregateDecl::Generator; }
 	| MUTEX GENERATOR
-		{ SemanticError( yylloc, "monitor generator is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
+		{
+			SemanticError( yylloc, "monitor generator is currently unimplemented." );
+			$$ = ast::AggregateDecl::NoAggregate;
+		}
 	| COROUTINE
-		{ $$ = AggregateDecl::Coroutine; }
+		{ $$ = ast::AggregateDecl::Coroutine; }
 	| MUTEX COROUTINE
-		{ SemanticError( yylloc, "monitor coroutine is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
+		{
+			SemanticError( yylloc, "monitor coroutine is currently unimplemented." );
+			$$ = ast::AggregateDecl::NoAggregate;
+		}
 	| THREAD
-		{ $$ = AggregateDecl::Thread; }
+		{ $$ = ast::AggregateDecl::Thread; }
 	| MUTEX THREAD
-		{ SemanticError( yylloc, "monitor thread is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
+		{
+			SemanticError( yylloc, "monitor thread is currently unimplemented." );
+			$$ = ast::AggregateDecl::NoAggregate;
+		}
 	;
 
@@ -2889,5 +2904,5 @@
 	designator_list ':'									// C99, CFA uses ":" instead of "="
 	| identifier_at ':'									// GCC, field name
-		{ $$ = new ExpressionNode( build_varref( $1 ) ); }
+		{ $$ = new ExpressionNode( build_varref( yylloc, $1 ) ); }
 	;
 
@@ -2901,5 +2916,5 @@
 designator:
 	'.' identifier_at									// C99, field name
-		{ $$ = new ExpressionNode( build_varref( $2 ) ); }
+		{ $$ = new ExpressionNode( build_varref( yylloc, $2 ) ); }
 	| '[' push assignment_expression pop ']'			// C99, single array element
 		// assignment_expression used instead of constant_expression because of shift/reduce conflicts with tuple.
@@ -2908,5 +2923,5 @@
 		{ $$ = $3; }
 	| '[' push constant_expression ELLIPSIS constant_expression pop ']' // GCC, multiple array elements
-		{ $$ = new ExpressionNode( new RangeExpr( maybeMoveBuild( $3 ), maybeMoveBuild( $5 ) ) ); }
+		{ $$ = new ExpressionNode( new ast::RangeExpr( yylloc, maybeMoveBuild( $3 ), maybeMoveBuild( $5 ) ) ); }
 	| '.' '[' push field_name_list pop ']'				// CFA, tuple field selector
 		{ $$ = $4; }
@@ -2948,7 +2963,7 @@
 		{
 			typedefTable.addToScope( *$2, TYPEDEFname, "9" );
-			if ( $1 == TypeDecl::Otype ) { SemanticError( yylloc, "otype keyword is deprecated, use T " ); }
-			if ( $1 == TypeDecl::Dtype ) { SemanticError( yylloc, "dtype keyword is deprecated, use T &" ); }
-			if ( $1 == TypeDecl::Ttype ) { SemanticError( yylloc, "ttype keyword is deprecated, use T ..." ); }
+			if ( $1 == ast::TypeDecl::Otype ) { SemanticError( yylloc, "otype keyword is deprecated, use T " ); }
+			if ( $1 == ast::TypeDecl::Dtype ) { SemanticError( yylloc, "dtype keyword is deprecated, use T &" ); }
+			if ( $1 == ast::TypeDecl::Ttype ) { SemanticError( yylloc, "ttype keyword is deprecated, use T ..." ); }
 		}
 	  type_initializer_opt assertion_list_opt
@@ -2961,33 +2976,33 @@
 		{
 			typedefTable.addToScope( *$2, TYPEDIMname, "9" );
-			$$ = DeclarationNode::newTypeParam( TypeDecl::Dimension, $2 );
+			$$ = DeclarationNode::newTypeParam( ast::TypeDecl::Dimension, $2 );
 		}
 	// | type_specifier identifier_parameter_declarator
 	| assertion_list
-		{ $$ = DeclarationNode::newTypeParam( TypeDecl::Dtype, new string( DeclarationNode::anonymous.newName() ) )->addAssertions( $1 ); }
+		{ $$ = DeclarationNode::newTypeParam( ast::TypeDecl::Dtype, new string( DeclarationNode::anonymous.newName() ) )->addAssertions( $1 ); }
 	;
 
 new_type_class:											// CFA
 	// empty
-		{ $$ = TypeDecl::Otype; }
+		{ $$ = ast::TypeDecl::Otype; }
 	| '&'
-		{ $$ = TypeDecl::Dtype; }
+		{ $$ = ast::TypeDecl::Dtype; }
 	| '*'
-		{ $$ = TypeDecl::DStype; }						// dtype + sized
+		{ $$ = ast::TypeDecl::DStype; }						// dtype + sized
 	// | '(' '*' ')'
-	// 	{ $$ = TypeDecl::Ftype; }
+	// 	{ $$ = ast::TypeDecl::Ftype; }
 	| ELLIPSIS
-		{ $$ = TypeDecl::Ttype; }
+		{ $$ = ast::TypeDecl::Ttype; }
 	;
 
 type_class:												// CFA
 	OTYPE
-		{ $$ = TypeDecl::Otype; }
+		{ $$ = ast::TypeDecl::Otype; }
 	| DTYPE
-		{ $$ = TypeDecl::Dtype; }
+		{ $$ = ast::TypeDecl::Dtype; }
 	| FTYPE
-		{ $$ = TypeDecl::Ftype; }
+		{ $$ = ast::TypeDecl::Ftype; }
 	| TTYPE
-		{ $$ = TypeDecl::Ttype; }
+		{ $$ = ast::TypeDecl::Ttype; }
 	;
 
@@ -3015,8 +3030,8 @@
 type_list:												// CFA
 	type
-		{ $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( $1 ) ) ); }
+		{ $$ = new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $1 ) ) ); }
 	| assignment_expression
 	| type_list ',' type
-		{ $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new TypeExpr( maybeMoveBuildType( $3 ) ) ) )); }
+		{ $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) )); }
 	| type_list ',' assignment_expression
 		{ $$ = (ExpressionNode *)( $1->set_last( $3 )); }
@@ -3125,5 +3140,5 @@
 external_definition:
 	DIRECTIVE
-		{ $$ = DeclarationNode::newDirectiveStmt( new StatementNode( build_directive( $1 ) ) ); }
+		{ $$ = DeclarationNode::newDirectiveStmt( new StatementNode( build_directive( yylloc, $1 ) ) ); }
 	| declaration
 		{
@@ -3131,5 +3146,5 @@
 			// unit, which is a dubious task, especially because C uses name rather than structural typing; hence it is
 			// disallowed at the moment.
-			if ( $1->linkage == LinkageSpec::Cforall && ! $1->storageClasses.is_static && $1->type && $1->type->kind == TypeData::AggregateInst ) {
+			if ( $1->linkage == ast::Linkage::Cforall && ! $1->storageClasses.is_static && $1->type && $1->type->kind == TypeData::AggregateInst ) {
 				if ( $1->type->aggInst.aggregate->kind == TypeData::Enum && $1->type->aggInst.aggregate->enumeration.anon ) {
 					SemanticError( yylloc, "extern anonymous enumeration is currently unimplemented." ); $$ = nullptr;
@@ -3158,9 +3173,9 @@
 		}
 	| ASM '(' string_literal ')' ';'					// GCC, global assembler statement
-		{ $$ = DeclarationNode::newAsmStmt( new StatementNode( build_asm( false, $3, nullptr ) ) ); }
+		{ $$ = DeclarationNode::newAsmStmt( new StatementNode( build_asm( yylloc, false, $3, nullptr ) ) ); }
 	| EXTERN STRINGliteral
 		{
 			linkageStack.push( linkage );				// handle nested extern "C"/"Cforall"
-			linkage = LinkageSpec::update( yylloc, linkage, $2 );
+			linkage = ast::Linkage::update( yylloc, linkage, $2 );
 		}
 	  up external_definition down
@@ -3173,5 +3188,5 @@
 		{
 			linkageStack.push( linkage );				// handle nested extern "C"/"Cforall"
-			linkage = LinkageSpec::update( yylloc, linkage, $2 );
+			linkage = ast::Linkage::update( yylloc, linkage, $2 );
 		}
 	  '{' up external_definition_list_opt down '}'
@@ -3297,5 +3312,5 @@
 subrange:
 	constant_expression '~' constant_expression			// CFA, integer subrange
-		{ $$ = new ExpressionNode( new RangeExpr( maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }
+		{ $$ = new ExpressionNode( new ast::RangeExpr( yylloc, maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }
 	;
 
@@ -3826,12 +3841,12 @@
 array_type_list:
 	basic_type_name
-		{ $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( $1 ) ) ); }
+		{ $$ = new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $1 ) ) ); }
 	| type_name
-		{ $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( $1 ) ) ); }
+		{ $$ = new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $1 ) ) ); }
 	| assignment_expression upupeq assignment_expression
 	| array_type_list ',' basic_type_name
-		{ $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new TypeExpr( maybeMoveBuildType( $3 ) ) ) )); }
-	| array_type_list ',' type_name 
-		{ $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new TypeExpr( maybeMoveBuildType( $3 ) ) ) )); }
+		{ $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) )); }
+	| array_type_list ',' type_name
+		{ $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) )); }
 	| array_type_list ',' assignment_expression upupeq assignment_expression
 	;
Index: src/Parser/parserutility.cc
===================================================================
--- src/Parser/parserutility.cc	(revision 70056edafe6b115773f5da41e81a7b2adf5c08f5)
+++ src/Parser/parserutility.cc	(revision e02e13fc53b4a6d659a7753b2c843a4b7e203c0d)
@@ -10,6 +10,6 @@
 // Created On       : Sat May 16 15:30:39 2015
 // Last Modified By : Andrew Beach
-// Last Modified On : Tus Jul 18 10:12:00 2017
-// Update Count     : 8
+// Last Modified On : Wed Mar  1 10:42:00 2023
+// Update Count     : 9
 //
 
@@ -19,7 +19,6 @@
 #include <string>                // for string
 
-#include "SynTree/Constant.h"    // for Constant
-#include "SynTree/Expression.h"  // for UntypedExpr, CastExpr, ConstantExpr
-#include "SynTree/Type.h"        // for BasicType, ZeroType, BasicType::Kind...
+#include "AST/Expr.hpp"          // for UntypedExpr, CastExpr, ConstantExpr
+#include "AST/Type.hpp"          // for BasicType, ZeroType, BasicType::Kind...
 
 // rewrite
@@ -28,10 +27,19 @@
 //    if ( (int)(x != 0) ) ...
 
-Expression *notZeroExpr( Expression *orig ) {
-	if( !orig ) return nullptr;
-	UntypedExpr *comparison = new UntypedExpr( new NameExpr( "?!=?" ) );
-	comparison->get_args().push_back( orig );
-	comparison->get_args().push_back( new ConstantExpr( Constant( new ZeroType( noQualifiers ), "0", (unsigned long long int)0 ) ) );
-	return new CastExpr( comparison, new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
+ast::Expr * notZeroExpr( ast::Expr * orig ) {
+	return ( !orig ) ? nullptr : new ast::CastExpr( orig->location,
+		ast::UntypedExpr::createCall( orig->location,
+			"?!=?",
+			{
+				orig,
+				new ast::ConstantExpr( orig->location,
+					new ast::ZeroType(),
+					"0",
+					std::optional<unsigned long long>( 0 )
+				),
+			}
+		),
+		new ast::BasicType( ast::BasicType::SignedInt )
+	);
 }
 
Index: src/Parser/parserutility.h
===================================================================
--- src/Parser/parserutility.h	(revision 70056edafe6b115773f5da41e81a7b2adf5c08f5)
+++ src/Parser/parserutility.h	(revision e02e13fc53b4a6d659a7753b2c843a4b7e203c0d)
@@ -10,13 +10,16 @@
 // Created On       : Sat May 16 15:31:46 2015
 // Last Modified By : Andrew Beach
-// Last Modified On : Thr Mar  9 12:16:00 2023
-// Update Count     : 6
+// Last Modified On : Tue Apr  4 14:03:00 2023
+// Update Count     : 7
 //
 
 #pragma once
 
-class Expression;
+#include "AST/Copy.hpp"            // for shallowCopy
+namespace ast {
+	class Expr;
+}
 
-Expression *notZeroExpr( Expression *orig );
+ast::Expr * notZeroExpr( ast::Expr *orig );
 
 template< typename T >
@@ -32,4 +35,9 @@
 }
 
+template<typename node_t>
+node_t * maybeCopy( node_t const * node ) {
+	return node ? ast::shallowCopy( node ) : nullptr;
+}
+
 // Local Variables: //
 // tab-width: 4 //
