Index: src/Parser/DeclarationNode.cc
===================================================================
--- src/Parser/DeclarationNode.cc	(revision bbf2cb164e26be1589f185df9bf81b21c503c1d2)
+++ src/Parser/DeclarationNode.cc	(revision f6e8c672a67785468988dfd68943c378679cbddf)
@@ -82,4 +82,6 @@
 
 DeclarationNode::~DeclarationNode() {
+	delete name;
+
 //	delete variable.name;
 	delete variable.assertions;
@@ -99,8 +101,7 @@
 DeclarationNode * DeclarationNode::clone() const {
 	DeclarationNode * newnode = new DeclarationNode;
-	newnode->set_next( maybeCopy( get_next() ) );
+	newnode->next = maybeCopy( next );
 	newnode->name = name ? new string( *name ) : nullptr;
 
-	newnode->builtin = NoBuiltinType;
 	newnode->type = maybeCopy( type );
 	newnode->inLine = inLine;
@@ -170,5 +171,5 @@
 
 void DeclarationNode::printList( std::ostream & os, int indent ) const {
-	ParseNode::printList( os, indent );
+	ParseList::printList( os, indent );
 	if ( hasEllipsis ) {
 		os << string( indent, ' ' )  << "and a variable number of other arguments" << endl;
@@ -433,6 +434,5 @@
 	DeclarationNode * newnode = new DeclarationNode;
 	newnode->type = new TypeData( TypeData::Builtin );
-	newnode->builtin = bt;
-	newnode->type->builtintype = newnode->builtin;
+	newnode->type->builtintype = bt;
 	return newnode;
 } // DeclarationNode::newBuiltinType
@@ -554,15 +554,4 @@
 } // DeclarationNode::copySpecifiers
 
-static void addQualifiersToType( TypeData *& src, TypeData * dst ) {
-	if ( dst->base ) {
-		addQualifiersToType( src, dst->base );
-	} else if ( dst->kind == TypeData::Function ) {
-		dst->base = src;
-		src = nullptr;
-	} else {
-		dst->qualifiers |= src->qualifiers;
-	} // if
-} // addQualifiersToType
-
 DeclarationNode * DeclarationNode::addQualifiers( DeclarationNode * q ) {
 	if ( ! q ) { return this; }							// empty qualifier
@@ -580,26 +569,11 @@
 	} // if
 
-	if ( q->type->forall ) {							// forall qualifier ?
-		if ( type->forall ) {							// polymorphic routine ?
-			type->forall->appendList( q->type->forall ); // augment forall qualifier
-		} else {
-			if ( type->kind == TypeData::Aggregate ) {	// struct/union ?
-				if ( type->aggregate.params ) {			// polymorphic ?
-					type->aggregate.params->appendList( q->type->forall ); // augment forall qualifier
-				} else {								// not polymorphic
-					type->aggregate.params = q->type->forall; // set forall qualifier
-				} // if
-			} else {									// not polymorphic
-				type->forall = q->type->forall;			// make polymorphic routine
-			} // if
-		} // if
-		q->type->forall = nullptr;						// forall qualifier moved
-	} // if
-
 	checkQualifiers( type, q->type );
+	BuiltinType const builtin = type->builtintype;
 	if ( (builtin == Zero || builtin == One) && q->type->qualifiers.any() && error.length() == 0 ) {
 		SemanticWarning( yylloc, Warning::BadQualifiersZeroOne, builtinTypeNames[builtin] );
 	} // if
-	addQualifiersToType( q->type, type );
+	type = ::addQualifiers( q->type, type );
+	q->type = nullptr;
 
 	delete q;
@@ -607,124 +581,29 @@
 } // addQualifiers
 
-static void addTypeToType( TypeData *& src, TypeData *& dst ) {
-	if ( src->forall && dst->kind == TypeData::Function ) {
-		if ( dst->forall ) {
-			dst->forall->appendList( src->forall );
-		} else {
-			dst->forall = src->forall;
-		} // if
-		src->forall = nullptr;
-	} // if
-	if ( dst->base ) {
-		addTypeToType( src, dst->base );
-	} else {
-		switch ( dst->kind ) {
-		case TypeData::Unknown:
-			src->qualifiers |= dst->qualifiers;
-			dst = src;
-			src = nullptr;
-			break;
-		case TypeData::Basic:
-			dst->qualifiers |= src->qualifiers;
-			if ( src->kind != TypeData::Unknown ) {
-				assert( src->kind == TypeData::Basic );
-
-				if ( dst->basictype == DeclarationNode::NoBasicType ) {
-					dst->basictype = src->basictype;
-				} else if ( src->basictype != DeclarationNode::NoBasicType )
-					SemanticError( yylloc, "multiple declaration types \"%s\" and \"%s\".",
-								   DeclarationNode::basicTypeNames[ dst->basictype ],
-								   DeclarationNode::basicTypeNames[ src->basictype ] );
-				if ( dst->complextype == DeclarationNode::NoComplexType ) {
-					dst->complextype = src->complextype;
-				} else if ( src->complextype != DeclarationNode::NoComplexType )
-					SemanticError( yylloc, "multiple declaration types \"%s\" and \"%s\".",
-								   DeclarationNode::complexTypeNames[ src->complextype ],
-								   DeclarationNode::complexTypeNames[ src->complextype ] );
-				if ( dst->signedness == DeclarationNode::NoSignedness ) {
-					dst->signedness = src->signedness;
-				} else if ( src->signedness != DeclarationNode::NoSignedness )
-					SemanticError( yylloc, "conflicting type specifier \"%s\" and \"%s\".",
-								   DeclarationNode::signednessNames[ dst->signedness ],
-								   DeclarationNode::signednessNames[ src->signedness ] );
-				if ( dst->length == DeclarationNode::NoLength ) {
-					dst->length = src->length;
-				} else if ( dst->length == DeclarationNode::Long && src->length == DeclarationNode::Long ) {
-					dst->length = DeclarationNode::LongLong;
-				} else if ( src->length != DeclarationNode::NoLength )
-					SemanticError( yylloc, "conflicting type specifier \"%s\" and \"%s\".",
-								   DeclarationNode::lengthNames[ dst->length ],
-								   DeclarationNode::lengthNames[ src->length ] );
-			} // if
-			break;
-		default:
-			switch ( src->kind ) {
-			case TypeData::Aggregate:
-			case TypeData::Enum:
-				dst->base = new TypeData( TypeData::AggregateInst );
-				dst->base->aggInst.aggregate = src;
-				if ( src->kind == TypeData::Aggregate ) {
-					dst->base->aggInst.params = maybeCopy( src->aggregate.actuals );
-				} // if
-				dst->base->qualifiers |= src->qualifiers;
-				src = nullptr;
-				break;
-			default:
-				if ( dst->forall ) {
-					dst->forall->appendList( src->forall );
-				} else {
-					dst->forall = src->forall;
-				} // if
-				src->forall = nullptr;
-				dst->base = src;
-				src = nullptr;
-			} // switch
-		} // switch
-	} // if
-}
-
 DeclarationNode * DeclarationNode::addType( DeclarationNode * o, bool copyattr ) {
-	if ( o ) {
-		checkSpecifiers( o );
-		copySpecifiers( o, copyattr );
-		if ( o->type ) {
-			if ( ! type ) {
-				if ( o->type->kind == TypeData::Aggregate || o->type->kind == TypeData::Enum ) {
-					// Hide type information aggregate instances.
-					type = new TypeData( TypeData::AggregateInst );
-					type->aggInst.aggregate = o->type;	// change ownership
-					type->aggInst.aggregate->aggregate.attributes.swap( o->attributes ); // change ownership					
-					if ( o->type->kind == TypeData::Aggregate ) {
-						type->aggInst.hoistType = o->type->aggregate.body;
-						type->aggInst.params = maybeCopy( o->type->aggregate.actuals );
-					} else {
-						type->aggInst.hoistType = o->type->enumeration.body;
-					} // if
-					type->qualifiers |= o->type->qualifiers;
-				} else {
-					type = o->type;
-				} // if
-				o->type = nullptr;						// change ownership
-			} else {
-				addTypeToType( o->type, type );
-			} // if
-		} // if
-		if ( o->bitfieldWidth ) {
-			bitfieldWidth = o->bitfieldWidth;
-		} // if
-
-		// there may be typedefs chained onto the type
-		if ( o->get_next() ) {
-			set_last( o->get_next()->clone() );
-		} // if
-	} // if
+	if ( !o ) return this;
+
+	checkSpecifiers( o );
+	copySpecifiers( o, copyattr );
+	if ( o->type ) {
+		type = ::addType( o->type, type, o->attributes );
+		o->type = nullptr;
+	} // if
+	if ( o->bitfieldWidth ) {
+		bitfieldWidth = o->bitfieldWidth;
+	} // if
+
+	// there may be typedefs chained onto the type
+	if ( o->next ) {
+		set_last( o->next->clone() );
+	} // if
+
 	delete o;
-
 	return this;
 }
 
 DeclarationNode * DeclarationNode::addEnumBase( DeclarationNode * o ) {
-	if ( o && o->type)  {
-		type->base= o->type;
+	if ( o && o->type ) {
+		type->base = o->type;
 	} // if
 	delete o;
@@ -745,5 +624,5 @@
 	if ( variable.tyClass != ast::TypeDecl::NUMBER_OF_KINDS ) {
 		if ( variable.assertions ) {
-			variable.assertions->appendList( assertions );
+			variable.assertions->set_last( assertions );
 		} else {
 			variable.assertions = assertions;
@@ -756,5 +635,5 @@
 	case TypeData::Symbolic:
 		if ( type->symbolic.assertions ) {
-			type->symbolic.assertions->appendList( assertions );
+			type->symbolic.assertions->set_last( assertions );
 		} else {
 			type->symbolic.assertions = assertions;
@@ -810,11 +689,5 @@
 DeclarationNode * DeclarationNode::setBase( TypeData * newType ) {
 	if ( type ) {
-		TypeData * prevBase = type;
-		TypeData * curBase = type->base;
-		while ( curBase != nullptr ) {
-			prevBase = curBase;
-			curBase = curBase->base;
-		} // while
-		prevBase->base = newType;
+		type->setLastBase( newType );
 	} else {
 		type = newType;
@@ -857,18 +730,5 @@
 		assert( p->type->kind == TypeData::Pointer || p->type->kind == TypeData::Reference );
 		if ( type ) {
-			switch ( type->kind ) {
-			case TypeData::Aggregate:
-			case TypeData::Enum:
-				p->type->base = new TypeData( TypeData::AggregateInst );
-				p->type->base->aggInst.aggregate = type;
-				if ( type->kind == TypeData::Aggregate ) {
-					p->type->base->aggInst.params = maybeCopy( type->aggregate.actuals );
-				} // if
-				p->type->base->qualifiers |= type->qualifiers;
-				break;
-
-			default:
-				p->type->base = type;
-			} // switch
+			p->type->base = makeNewBase( type );
 			type = nullptr;
 		} // if
@@ -880,31 +740,9 @@
 }
 
-static TypeData * findLast( TypeData * a ) {
-	assert( a );
-	TypeData * cur = a;
-	while ( cur->base ) {
-		cur = cur->base;
-	} // while
-	return cur;
-}
-
 DeclarationNode * DeclarationNode::addNewArray( DeclarationNode * a ) {
 	if ( ! a ) return this;
 	assert( a->type->kind == TypeData::Array );
-	TypeData * lastArray = findLast( a->type );
 	if ( type ) {
-		switch ( type->kind ) {
-		case TypeData::Aggregate:
-		case TypeData::Enum:
-			lastArray->base = new TypeData( TypeData::AggregateInst );
-			lastArray->base->aggInst.aggregate = type;
-			if ( type->kind == TypeData::Aggregate ) {
-				lastArray->base->aggInst.params = maybeCopy( type->aggregate.actuals );
-			} // if
-			lastArray->base->qualifiers |= type->qualifiers;
-			break;
-		default:
-			lastArray->base = type;
-		} // switch
+		a->type->setLastBase( makeNewBase( type ) );
 		type = nullptr;
 	} // if
@@ -960,38 +798,7 @@
 DeclarationNode * DeclarationNode::cloneBaseType( DeclarationNode * o, bool copyattr ) {
 	if ( ! o ) return nullptr;
-
 	o->copySpecifiers( this, copyattr );
 	if ( type ) {
-		TypeData * srcType = type;
-
-		// search for the base type by scanning off pointers and array designators
-		while ( srcType->base ) {
-			srcType = srcType->base;
-		} // while
-
-		TypeData * newType = srcType->clone();
-		if ( newType->kind == TypeData::AggregateInst ) {
-			// don't duplicate members
-			if ( newType->aggInst.aggregate->kind == TypeData::Enum ) {
-				delete newType->aggInst.aggregate->enumeration.constants;
-				newType->aggInst.aggregate->enumeration.constants = nullptr;
-				newType->aggInst.aggregate->enumeration.body = false;
-			} else {
-				assert( newType->aggInst.aggregate->kind == TypeData::Aggregate );
-				delete newType->aggInst.aggregate->aggregate.fields;
-				newType->aggInst.aggregate->aggregate.fields = nullptr;
-				newType->aggInst.aggregate->aggregate.body = false;
-			} // if
-			// don't hoist twice
-			newType->aggInst.hoistType = false;
-		} // if
-
-		newType->forall = maybeCopy( type->forall );
-		if ( ! o->type ) {
-			o->type = newType;
-		} else {
-			addTypeToType( newType, o->type );
-			delete newType;
-		} // if
+		o->type = ::cloneBaseType( type, o->type );
 	} // if
 	return o;
@@ -1099,5 +906,5 @@
 	std::back_insert_iterator<std::vector<ast::ptr<ast::Decl>>> out( outputList );
 
-	for ( const DeclarationNode * cur = firstNode ; cur ; cur = strict_next( cur ) ) {
+	for ( const DeclarationNode * cur = firstNode ; cur ; cur = cur->next ) {
 		try {
 			bool extracted_named = false;
@@ -1167,5 +974,5 @@
 	std::back_insert_iterator<std::vector<ast::ptr<ast::DeclWithType>>> out( outputList );
 
-	for ( const DeclarationNode * cur = firstNode; cur; cur = strict_next( cur ) ) {
+	for ( const DeclarationNode * cur = firstNode; cur; cur = cur->next ) {
 		try {
 			ast::Decl * decl = cur->build();
@@ -1217,5 +1024,5 @@
 	std::back_insert_iterator<std::vector<ast::ptr<ast::Type>>> out( outputList );
 
-	for ( const DeclarationNode * cur = firstNode ; cur ; cur = strict_next( cur ) ) {
+	for ( const DeclarationNode * cur = firstNode ; cur ; cur = cur->next ) {
 		try {
 			* out++ = cur->buildType();
Index: src/Parser/DeclarationNode.h
===================================================================
--- src/Parser/DeclarationNode.h	(revision bbf2cb164e26be1589f185df9bf81b21c503c1d2)
+++ src/Parser/DeclarationNode.h	(revision f6e8c672a67785468988dfd68943c378679cbddf)
@@ -19,7 +19,7 @@
 
 struct TypeData;
-class InitializerNode;
-
-struct DeclarationNode : public ParseNode {
+struct InitializerNode;
+
+struct DeclarationNode final : public ParseList<DeclarationNode> {
 	// These enumerations must harmonize with their names in DeclarationNode.cc.
 	enum BasicType {
@@ -108,8 +108,4 @@
 	DeclarationNode * cloneBaseType( DeclarationNode * newdecl, bool = true );
 
-	DeclarationNode * appendList( DeclarationNode * node ) {
-		return (DeclarationNode *)set_last( node );
-	}
-
 	virtual void print( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const override;
 	virtual void printList( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const override;
@@ -129,5 +125,5 @@
 	DeclarationNode * set_inLine( bool inL ) { inLine = inL; return this; }
 
-	DeclarationNode * get_last() { return (DeclarationNode *)ParseNode::get_last(); }
+	const std::string * name = nullptr;
 
 	struct Variable_t {
@@ -144,6 +140,4 @@
 	};
 	StaticAssert_t assert;
-
-	BuiltinType builtin = NoBuiltinType;
 
 	TypeData * type = nullptr;
@@ -177,12 +171,4 @@
 }
 
-template<typename NodeType>
-NodeType * strict_next( NodeType * node ) {
-	ParseNode * next = node->get_next();
-	if ( nullptr == next ) return nullptr;
-	if ( NodeType * ret = dynamic_cast<NodeType *>( next ) ) return ret;
-	SemanticError( next->location, "internal error, non-homogeneous nodes founds in buildList processing." );
-}
-
 // This generic buildList is here along side its overloads.
 template<typename AstType, typename NodeType,
@@ -193,5 +179,5 @@
 	std::back_insert_iterator<Container<ast::ptr<AstType>, Args...>> out( output );
 
-	for ( NodeType * cur = firstNode ; cur ; cur = strict_next( cur ) ) {
+	for ( NodeType * cur = firstNode ; cur ; cur = cur->next ) {
 		try {
 			AstType * node = dynamic_cast<AstType *>( maybeBuild( cur ) );
Index: src/Parser/ExpressionNode.h
===================================================================
--- src/Parser/ExpressionNode.h	(revision bbf2cb164e26be1589f185df9bf81b21c503c1d2)
+++ src/Parser/ExpressionNode.h	(revision f6e8c672a67785468988dfd68943c378679cbddf)
@@ -18,14 +18,14 @@
 #include "ParseNode.h"
 
-class InitializerNode;
+struct InitializerNode;
 
-class ExpressionNode final : public ParseNode {
-public:
+struct ExpressionNode final : public ParseList<ExpressionNode> {
 	ExpressionNode( ast::Expr * expr = nullptr ) : expr( expr ) {}
 	virtual ~ExpressionNode() {}
 	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() ) ));
+		ExpressionNode * node = new ExpressionNode( ast::shallowCopy( expr.get() ) );
+		node->next = maybeCopy( next );
+		return node;
 	}
 
Index: src/Parser/InitializerNode.cc
===================================================================
--- src/Parser/InitializerNode.cc	(revision bbf2cb164e26be1589f185df9bf81b21c503c1d2)
+++ src/Parser/InitializerNode.cc	(revision f6e8c672a67785468988dfd68943c378679cbddf)
@@ -36,5 +36,5 @@
 		: expr( _expr ), aggregate( aggrp ), designator( des ), kids( nullptr ), maybeConstructed( true ), isDelete( false ) {
 	if ( aggrp )
-		kids = dynamic_cast< InitializerNode * >( get_next() );
+		kids = next;
 
 	if ( kids )
@@ -48,8 +48,8 @@
 
 	if ( aggrp )
-		kids = dynamic_cast< InitializerNode * >( get_next() );
+		kids = next;
 
 	if ( kids )
-		set_next( nullptr );
+		next = nullptr;
 } // InitializerNode::InitializerNode
 
@@ -73,5 +73,5 @@
 			while ( curdes != nullptr) {
 				curdes->printOneLine(os);
-				curdes = (ExpressionNode *)(curdes->get_next());
+				curdes = curdes->next;
 				if ( curdes ) os << ", ";
 			} // while
@@ -87,5 +87,5 @@
 
 	InitializerNode *moreInit;
-	if ( (moreInit = dynamic_cast< InitializerNode * >( get_next() ) ) ) {
+	if ( ( moreInit = next ) ) {
 		moreInit->printOneLine( os );
 	} // if
@@ -98,5 +98,5 @@
 		std::vector<ast::ptr<ast::Designation>> designlist;
 		InitializerNode * child = next_init();
-		for ( ; child != nullptr ; child = dynamic_cast< InitializerNode * >( child->get_next() ) ) {
+		for ( ; child != nullptr ; child = child->next ) {
 			std::deque<ast::ptr<ast::Expr>> desList;
 			buildList( child->designator, desList );
Index: src/Parser/InitializerNode.h
===================================================================
--- src/Parser/InitializerNode.h	(revision bbf2cb164e26be1589f185df9bf81b21c503c1d2)
+++ src/Parser/InitializerNode.h	(revision f6e8c672a67785468988dfd68943c378679cbddf)
@@ -18,6 +18,5 @@
 #include "ParseNode.h"
 
-class InitializerNode : public ParseNode {
-public:
+struct InitializerNode final : public ParseList<InitializerNode> {
 	InitializerNode( ExpressionNode *, bool aggrp = false, ExpressionNode * des = nullptr );
 	InitializerNode( InitializerNode *, bool aggrp = false, ExpressionNode * des = nullptr );
Index: src/Parser/ParseNode.h
===================================================================
--- src/Parser/ParseNode.h	(revision bbf2cb164e26be1589f185df9bf81b21c503c1d2)
+++ src/Parser/ParseNode.h	(revision f6e8c672a67785468988dfd68943c378679cbddf)
@@ -33,6 +33,6 @@
 
 struct DeclarationNode;
-class InitializerNode;
-class ExpressionNode;
+struct InitializerNode;
+struct ExpressionNode;
 struct StatementNode;
 
@@ -45,24 +45,33 @@
 extern YYLTYPE yylloc;
 
-class ParseNode {
-  public:
-	ParseNode() {};
-	virtual ~ParseNode() { delete next; delete name; };
+struct ParseNode {
+	ParseNode() {}
+	virtual ~ParseNode() {}
 	virtual ParseNode * clone() const = 0;
 
-	ParseNode * get_next() const { return next; }
-	ParseNode * set_next( ParseNode * newlink ) { next = newlink; return this; }
+	virtual void print( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const {}
 
-	ParseNode * get_last() {
-		ParseNode * current;
-		for ( current = this; current->get_next() != nullptr; current = current->get_next() );
+	static int indent_by;
+
+	CodeLocation location = yylloc;
+}; // ParseNode
+
+/// Only ever use in the form `struct NAME final : public ParseList<NAME>`!
+template<typename Next>
+struct ParseList : public ParseNode {
+	ParseList() {}
+	virtual ~ParseList() { delete next; };
+	virtual ParseList<Next> * clone() const = 0;
+
+	Next * get_last() {
+		Next * current = static_cast<Next *>( this );
+		while ( current->next != nullptr ) current = current->next;
 		return current;
 	}
-	ParseNode * set_last( ParseNode * newlast ) {
-		if ( newlast != nullptr ) get_last()->set_next( newlast );
-		return this;
+	Next * set_last( Next * newlast ) {
+		if ( newlast != nullptr ) get_last()->next = newlast;
+		return static_cast<Next *>( this );
 	}
 
-	virtual void print( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const {}
 	virtual void printList( std::ostream & os, int indent = 0 ) const {
 		print( os, indent );
@@ -70,10 +79,6 @@
 	}
 
-	static int indent_by;
-
-	ParseNode * next = nullptr;
-	const std::string * name = nullptr;
-	CodeLocation location = yylloc;
-}; // ParseNode
+	Next * next = nullptr;
+};
 
 // Must harmonize with OperName.
Index: src/Parser/StatementNode.cc
===================================================================
--- src/Parser/StatementNode.cc	(revision bbf2cb164e26be1589f185df9bf81b21c503c1d2)
+++ src/Parser/StatementNode.cc	(revision f6e8c672a67785468988dfd68943c378679cbddf)
@@ -54,13 +54,13 @@
 		StatementNode * nextStmt = new StatementNode(
 			new ast::DeclStmt( decl->location, maybeBuild( decl ) ) );
-		set_next( nextStmt );
-		if ( decl->get_next() ) {
-			get_next()->set_next( new StatementNode( dynamic_cast< DeclarationNode * >(decl->get_next()) ) );
-			decl->set_next( 0 );
+		next = nextStmt;
+		if ( decl->next ) {
+			next->next = new StatementNode( decl->next );
+			decl->next = nullptr;
 		} // if
 	} else {
-		if ( decl->get_next() ) {
-			set_next( new StatementNode( dynamic_cast< DeclarationNode * >( decl->get_next() ) ) );
-			decl->set_next( 0 );
+		if ( decl->next ) {
+			next = new StatementNode( decl->next );
+			decl->next = nullptr;
 		} // if
 		agg = decl;
@@ -87,10 +87,10 @@
 	ClauseNode * prev = this;
 	// find end of list and maintain previous pointer
-	for ( ClauseNode * curr = prev; curr != nullptr; curr = (ClauseNode *)curr->get_next() ) {
-		ClauseNode * node = strict_dynamic_cast< ClauseNode * >(curr);
+	for ( ClauseNode * curr = prev; curr != nullptr; curr = curr->next ) {
+		ClauseNode * node = curr;
 		assert( dynamic_cast<ast::CaseClause *>( node->clause.get() ) );
 		prev = curr;
 	} // for
-	ClauseNode * node = dynamic_cast< ClauseNode * >(prev);
+	ClauseNode * node = prev;
 	// convert from StatementNode list to Statement list
 	std::vector<ast::ptr<ast::Stmt>> stmts;
@@ -332,6 +332,6 @@
 	clause->when_cond = notZeroExpr( maybeMoveBuild( when ) );
 
-	ExpressionNode * next = dynamic_cast<ExpressionNode *>( targetExpr->get_next() );
-	targetExpr->set_next( nullptr );
+	ExpressionNode * next = targetExpr->next;
+	targetExpr->next = nullptr;
 	buildMoveList( next, clause->target_args );
 
Index: src/Parser/StatementNode.h
===================================================================
--- src/Parser/StatementNode.h	(revision bbf2cb164e26be1589f185df9bf81b21c503c1d2)
+++ src/Parser/StatementNode.h	(revision f6e8c672a67785468988dfd68943c378679cbddf)
@@ -18,5 +18,5 @@
 #include "ParseNode.h"
 
-struct StatementNode final : public ParseNode {
+struct StatementNode final : public ParseList<StatementNode> {
 	StatementNode() : stmt( nullptr ) {}
 	StatementNode( ast::Stmt * stmt ) : stmt( stmt ) {}
@@ -39,12 +39,7 @@
 }; // StatementNode
 
-struct ClauseNode final : public ParseNode {
+struct ClauseNode final : public ParseList<ClauseNode> {
 	ClauseNode( ast::StmtClause * clause ) : clause( clause ) {}
 	virtual ~ClauseNode() {}
-
-	ClauseNode * set_last( ParseNode * newlast ) {
-		ParseNode::set_last( newlast );
-        return this;
-    }
 
 	virtual ClauseNode * clone() const final { assert( false ); return nullptr; }
Index: src/Parser/TypeData.cc
===================================================================
--- src/Parser/TypeData.cc	(revision bbf2cb164e26be1589f185df9bf81b21c503c1d2)
+++ src/Parser/TypeData.cc	(revision f6e8c672a67785468988dfd68943c378679cbddf)
@@ -479,4 +479,200 @@
 
 
+TypeData * TypeData::getLastBase() {
+	TypeData * cur = this;
+	while ( cur->base ) cur = cur->base;
+	return cur;
+}
+
+void TypeData::setLastBase( TypeData * newBase ) {
+	getLastBase()->base = newBase;
+}
+
+// Takes ownership of src.
+static void addQualifiersToType( TypeData * dst, TypeData * src ) {
+	if ( dst->base ) {
+		addQualifiersToType( dst->base, src );
+	} else if ( dst->kind == TypeData::Function ) {
+		dst->base = src;
+		src = nullptr;
+    } else {
+		dst->qualifiers |= src->qualifiers;
+		delete src;
+	} // if
+}
+
+// Takes ownership of all arguments, gives ownership of return value.
+TypeData * addQualifiers( TypeData * ltype, TypeData * rtype ) {
+	if ( ltype->forall ) {
+		if ( rtype->forall ) {
+			rtype->forall->set_last( ltype->forall );
+		} else if ( TypeData::Aggregate != rtype->kind ) {
+			rtype->forall = ltype->forall;
+		} else if ( rtype->aggregate.params ) {
+			rtype->aggregate.params->set_last( ltype->forall );
+		} else {
+			rtype->aggregate.params = ltype->forall;
+		}
+		ltype->forall = nullptr;
+	}
+
+	addQualifiersToType( rtype, ltype );
+	return rtype;
+}
+
+// Helper for addType and cloneBaseType.
+static void addTypeToType( TypeData *& dst, TypeData *& src ) {
+	if ( src->forall && dst->kind == TypeData::Function ) {
+		if ( dst->forall ) {
+			dst->forall->set_last( src->forall );
+		} else {
+			dst->forall = src->forall;
+		} // if
+		src->forall = nullptr;
+	} // if
+	if ( dst->base ) {
+		addTypeToType( dst->base, src );
+		return;
+	}
+	switch ( dst->kind ) {
+	case TypeData::Unknown:
+		src->qualifiers |= dst->qualifiers;
+		// LEAKS dst?
+		dst = src;
+		src = nullptr;
+		break;
+	case TypeData::Basic:
+		dst->qualifiers |= src->qualifiers;
+		if ( src->kind != TypeData::Unknown ) {
+			assert( src->kind == TypeData::Basic );
+
+			if ( dst->basictype == DeclarationNode::NoBasicType ) {
+				dst->basictype = src->basictype;
+			} else if ( src->basictype != DeclarationNode::NoBasicType ) {
+				SemanticError( yylloc, "multiple declaration types \"%s\" and \"%s\".",
+					DeclarationNode::basicTypeNames[ dst->basictype ],
+					DeclarationNode::basicTypeNames[ src->basictype ] );
+			}
+			if ( dst->complextype == DeclarationNode::NoComplexType ) {
+				dst->complextype = src->complextype;
+			} else if ( src->complextype != DeclarationNode::NoComplexType ) {
+				SemanticError( yylloc, "multiple declaration types \"%s\" and \"%s\".",
+					DeclarationNode::complexTypeNames[ src->complextype ],
+					DeclarationNode::complexTypeNames[ src->complextype ] );
+			}
+			if ( dst->signedness == DeclarationNode::NoSignedness ) {
+				dst->signedness = src->signedness;
+			} else if ( src->signedness != DeclarationNode::NoSignedness ) {
+				SemanticError( yylloc, "conflicting type specifier \"%s\" and \"%s\".",
+					DeclarationNode::signednessNames[ dst->signedness ],
+					DeclarationNode::signednessNames[ src->signedness ] );
+			}
+			if ( dst->length == DeclarationNode::NoLength ) {
+				dst->length = src->length;
+			} else if ( dst->length == DeclarationNode::Long && src->length == DeclarationNode::Long ) {
+				dst->length = DeclarationNode::LongLong;
+			} else if ( src->length != DeclarationNode::NoLength ) {
+				SemanticError( yylloc, "conflicting type specifier \"%s\" and \"%s\".",
+					DeclarationNode::lengthNames[ dst->length ],
+					DeclarationNode::lengthNames[ src->length ] );
+			}
+		} // if
+		break;
+	default:
+		switch ( src->kind ) {
+		case TypeData::Aggregate:
+		case TypeData::Enum:
+			dst->base = new TypeData( TypeData::AggregateInst );
+			dst->base->aggInst.aggregate = src;
+			if ( src->kind == TypeData::Aggregate ) {
+				dst->base->aggInst.params = maybeCopy( src->aggregate.actuals );
+			} // if
+			dst->base->qualifiers |= src->qualifiers;
+			src = nullptr;
+			break;
+		default:
+			if ( dst->forall ) {
+				dst->forall->set_last( src->forall );
+			} else {
+				dst->forall = src->forall;
+			} // if
+			src->forall = nullptr;
+			dst->base = src;
+			src = nullptr;
+		} // switch
+	} // switch
+}
+
+// Takes ownership of all arguments, gives ownership of return value.
+TypeData * addType( TypeData * ltype, TypeData * rtype, std::vector<ast::ptr<ast::Attribute>> & attributes ) {
+	if ( rtype ) {
+		addTypeToType( rtype, ltype );
+		return rtype;
+	} else {
+		if ( ltype->kind == TypeData::Aggregate || ltype->kind == TypeData::Enum ) {
+			// Hide type information aggregate instances.
+			rtype = new TypeData( TypeData::AggregateInst );
+			rtype->aggInst.aggregate = ltype;
+			rtype->aggInst.aggregate->aggregate.attributes.swap( attributes ); // change ownership
+			if ( ltype->kind == TypeData::Aggregate ) {
+				rtype->aggInst.hoistType = ltype->aggregate.body;
+				rtype->aggInst.params = maybeCopy( ltype->aggregate.actuals );
+			} else {
+				rtype->aggInst.hoistType = ltype->enumeration.body;
+			} // if
+			rtype->qualifiers |= ltype->qualifiers;
+		} else {
+			rtype = ltype;
+		} // if
+		return rtype;
+	} // if
+}
+
+// Takes ownership of both arguments, gives ownership of return value.
+TypeData * cloneBaseType( TypeData * type, TypeData * other ) {
+	TypeData * newType = type->getLastBase()->clone();
+	if ( newType->kind == TypeData::AggregateInst ) {
+		// don't duplicate members
+		if ( newType->aggInst.aggregate->kind == TypeData::Enum ) {
+			delete newType->aggInst.aggregate->enumeration.constants;
+			newType->aggInst.aggregate->enumeration.constants = nullptr;
+			newType->aggInst.aggregate->enumeration.body = false;
+		} else {
+			assert( newType->aggInst.aggregate->kind == TypeData::Aggregate );
+			delete newType->aggInst.aggregate->aggregate.fields;
+			newType->aggInst.aggregate->aggregate.fields = nullptr;
+			newType->aggInst.aggregate->aggregate.body = false;
+		} // if
+		// don't hoist twice
+		newType->aggInst.hoistType = false;
+	} // if
+	newType->forall = maybeCopy( type->forall );
+
+	if ( other ) {
+		addTypeToType( other, newType );
+		delete newType;
+		return other;
+	} // if
+	return newType;
+}
+
+TypeData * makeNewBase( TypeData * type ) {
+	switch ( type->kind ) {
+	case TypeData::Aggregate:
+	case TypeData::Enum: {
+		TypeData * out = new TypeData( TypeData::AggregateInst );
+		out->aggInst.aggregate = type;
+		if ( TypeData::Aggregate == type->kind ) {
+			out->aggInst.params = maybeCopy( type->aggregate.actuals );
+		}
+		out->qualifiers |= type->qualifiers;
+		return out;
+	}
+	default:
+		return type;
+	} // switch
+}
+
+
 void buildForall(
 		const DeclarationNode * firstNode,
@@ -494,5 +690,5 @@
 	for ( auto i = outputList.begin() ;
 			i != outputList.end() ;
-			++i, n = (DeclarationNode*)n->get_next() ) {
+			++i, n = n->next ) {
 		// Only the object type class adds additional assertions.
 		if ( n->variable.tyClass != ast::TypeDecl::Otype ) {
@@ -639,5 +835,5 @@
 	for ( auto i = outputForall.begin() ;
 			i != outputForall.end() ;
-			++i, n = (DeclarationNode*)n->get_next() ) {
+			++i, n = n->next ) {
 		// Only the object type class adds additional assertions.
 		if ( n->variable.tyClass != ast::TypeDecl::Otype ) {
@@ -1272,5 +1468,5 @@
 	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 ) {
+	for ( const DeclarationNode * cur = td->enumeration.constants; cur != nullptr; cur = cur->next, ++members ) {
 		if ( cur->enumInLine ) {
 			// Do Nothing
@@ -1500,7 +1696,7 @@
 	assert( ! function.params );
 	// loop over declaration first as it is easier to spot errors
-	for ( DeclarationNode * decl = function.oldDeclList; decl != nullptr; decl = dynamic_cast< DeclarationNode * >( decl->get_next() ) ) {
+	for ( DeclarationNode * decl = function.oldDeclList; decl != nullptr; decl = decl->next ) {
 		// scan ALL parameter names for each declaration name to check for duplicates
-		for ( DeclarationNode * param = function.idList; param != nullptr; param = dynamic_cast< DeclarationNode * >( param->get_next() ) ) {
+		for ( DeclarationNode * param = function.idList; param != nullptr; param = param->next ) {
 			if ( *decl->name == *param->name ) {
 				// type set => parameter name already transformed by a declaration names so there is a duplicate
@@ -1524,5 +1720,5 @@
 	//    rtb( a, b, c ) const char * b; {} => int rtn( int a, const char * b, int c ) {}
 
-	for ( DeclarationNode * param = function.idList; param != nullptr; param = dynamic_cast< DeclarationNode * >( param->get_next() ) ) {
+	for ( DeclarationNode * param = function.idList; param != nullptr; param = param->next ) {
 		if ( ! param->type ) {							// generate type int for empty parameter type
 			param->type = new TypeData( TypeData::Basic );
Index: src/Parser/TypeData.h
===================================================================
--- src/Parser/TypeData.h	(revision bbf2cb164e26be1589f185df9bf81b21c503c1d2)
+++ src/Parser/TypeData.h	(revision f6e8c672a67785468988dfd68943c378679cbddf)
@@ -111,5 +111,13 @@
 
 	const std::string * leafName() const;
+
+	TypeData * getLastBase();
+	void setLastBase( TypeData * );
 };
+
+TypeData * addQualifiers( TypeData * ltype, TypeData * rtype );
+TypeData * addType( TypeData * ltype, TypeData * rtype, std::vector<ast::ptr<ast::Attribute>> & );
+TypeData * cloneBaseType( TypeData * type, TypeData * other );
+TypeData * makeNewBase( TypeData * type );
 
 ast::Type * typebuild( const TypeData * );
Index: src/Parser/lex.ll
===================================================================
--- src/Parser/lex.ll	(revision bbf2cb164e26be1589f185df9bf81b21c503c1d2)
+++ src/Parser/lex.ll	(revision f6e8c672a67785468988dfd68943c378679cbddf)
@@ -10,6 +10,6 @@
  * Created On       : Sat Sep 22 08:58:10 2001
  * Last Modified By : Peter A. Buhr
- * Last Modified On : Tue Oct  3 17:10:57 2023
- * Update Count     : 773
+ * Last Modified On : Sat Feb 24 11:47:24 2024
+ * Update Count     : 777
  */
 
@@ -407,4 +407,5 @@
 ";"				{ ASCIIOP_RETURN(); }
 "."				{ ASCIIOP_RETURN(); }					// also operator
+"@@"			{ NAMEDOP_RETURN(ATTR); }				// CFA, attribute shorthand
 "..."			{ NAMEDOP_RETURN(ELLIPSIS); }
 
Index: src/Parser/parser.yy
===================================================================
--- src/Parser/parser.yy	(revision bbf2cb164e26be1589f185df9bf81b21c503c1d2)
+++ src/Parser/parser.yy	(revision f6e8c672a67785468988dfd68943c378679cbddf)
@@ -10,6 +10,6 @@
 // Created On       : Sat Sep  1 20:22:55 2001
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Feb 23 18:25:46 2024
-// Update Count     : 6484
+// Last Modified On : Mon Mar  4 08:44:25 2024
+// Update Count     : 6562
 //
 
@@ -126,6 +126,6 @@
 	DeclarationNode * cl = (new DeclarationNode)->addType( typeSpec ); // typeSpec IS DELETED!!!
 
-	// Start at second variable in declaration list and clone the type specifiers for each variable..
-	for ( DeclarationNode * cur = dynamic_cast<DeclarationNode *>( declList->get_next() ); cur != nullptr; cur = dynamic_cast<DeclarationNode *>( cur->get_next() ) ) {
+	// Start at second variable in declaration list and clone the type specifiers for each variable.
+	for ( DeclarationNode * cur = declList->next ; cur != nullptr; cur = cur->next ) {
 		cl->cloneBaseType( cur, copyattr );				// cur is modified
 	} // for
@@ -139,5 +139,5 @@
 void distExt( DeclarationNode * declaration ) {
 	// distribute EXTENSION across all declarations
-	for ( DeclarationNode *iter = declaration; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) {
+	for ( DeclarationNode *iter = declaration ; iter != nullptr ; iter = iter->next ) {
 		iter->set_extension( true );
 	} // for
@@ -146,5 +146,5 @@
 void distInl( DeclarationNode * declaration ) {
 	// distribute INLINE across all declarations
-	for ( DeclarationNode *iter = declaration; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) {
+	for ( DeclarationNode *iter = declaration ; iter != nullptr ; iter = iter->next ) {
 		iter->set_inLine( true );
 	} // for
@@ -153,5 +153,5 @@
 void distQual( DeclarationNode * declaration, DeclarationNode * qualifiers ) {
 	// distribute qualifiers across all non-variable declarations in a distribution statemement
-	for ( DeclarationNode * iter = declaration; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) {
+	for ( DeclarationNode * iter = declaration ; iter != nullptr ; iter = iter->next ) {
 		// SKULLDUGGERY: Distributions are parsed inside out, so qualifiers are added to declarations inside out. Since
 		// addQualifiers appends to the back of the list, the forall clauses are in the wrong order (right to left). To
@@ -389,5 +389,5 @@
 %token LE GE EQ NE										// <=	>=	==	!=
 %token ANDAND OROR										// &&	||
-%token ELLIPSIS											// ...
+%token ATTR ELLIPSIS									// @@	...
 
 %token EXPassign	MULTassign	DIVassign	MODassign	// \=	*=	/=	%=
@@ -433,5 +433,5 @@
 %type<stmt> statement					labeled_statement			compound_statement
 %type<stmt> statement_decl				statement_decl_list			statement_list_nodecl
-%type<stmt> selection_statement			if_statement
+%type<stmt> selection_statement
 %type<clause> switch_clause_list_opt	switch_clause_list
 %type<expr> case_value
@@ -500,5 +500,5 @@
 %type<decl> cfa_identifier_parameter_declarator_tuple cfa_identifier_parameter_ptr
 
-%type<decl> cfa_parameter_declaration cfa_parameter_list cfa_parameter_ellipsis_list_opt
+%type<decl> cfa_parameter_declaration cfa_parameter_list cfa_parameter_list_ellipsis_opt
 
 %type<decl> cfa_typedef_declaration cfa_variable_declaration cfa_variable_specifier
@@ -508,5 +508,5 @@
 %type<decl> KR_parameter_list KR_parameter_list_opt
 
-%type<decl> parameter_declaration parameter_list parameter_type_list_opt
+%type<decl> parameter_declaration parameter_list parameter_list_ellipsis_opt
 
 %type<decl> paren_identifier paren_type
@@ -530,5 +530,5 @@
 %type<decl> type_parameter type_parameter_list type_initializer_opt
 
-%type<expr> type_parameters_opt type_list array_type_list
+%type<expr> type_parameters_opt type_list array_type_list // array_dimension_list
 
 %type<decl> type_qualifier type_qualifier_name forall type_qualifier_list_opt type_qualifier_list
@@ -1246,9 +1246,16 @@
 	;
 
+// if, switch, and choose require parenthesis around the conditional because it can be followed by a statement.
+// For example, without parenthesis:
+//
+//    if x + y + z; => "if ( x + y ) + z" or "if ( x ) + y + z"
+//    switch ( S ) { ... } => switch ( S ) { compound literal... } ... or 
+
 selection_statement:
-			// pop causes a S/R conflict without separating the IF statement into a non-terminal even after resolving
-			// the inherent S/R conflict with THEN/ELSE.
-	push if_statement pop
-		{ $$ = $2; }
+	IF '(' conditional_declaration ')' statement		%prec THEN
+		// explicitly deal with the shift/reduce conflict on if/else
+		{ $$ = new StatementNode( build_if( yylloc, $3, maybe_build_compound( yylloc, $5 ), nullptr ) ); }
+	| IF '(' conditional_declaration ')' statement ELSE statement
+		{ $$ = new StatementNode( build_if( yylloc, $3, maybe_build_compound( yylloc, $5 ), maybe_build_compound( yylloc, $7 ) ) ); }
 	| SWITCH '(' comma_expression ')' case_clause
 		{ $$ = new StatementNode( build_switch( yylloc, true, $3, $5 ) ); }
@@ -1274,12 +1281,4 @@
 	| CHOOSE '(' comma_expression ')' '{' error '}'		// CFA, invalid syntax rule
 		{ SemanticError( yylloc, "syntax error, declarations can only appear before the list of case clauses." ); $$ = nullptr; }
-	;
-
-if_statement:
-	IF '(' conditional_declaration ')' statement		%prec THEN
-		// explicitly deal with the shift/reduce conflict on if/else
-		{ $$ = new StatementNode( build_if( yylloc, $3, maybe_build_compound( yylloc, $5 ), nullptr ) ); }
-	| IF '(' conditional_declaration ')' statement ELSE statement
-		{ $$ = new StatementNode( build_if( yylloc, $3, maybe_build_compound( yylloc, $5 ), maybe_build_compound( yylloc, $7 ) ) ); }
 	;
 
@@ -1897,5 +1896,6 @@
 declaration_list:
 	declaration
-	| declaration_list declaration		{ $$ = $1->appendList( $2 ); }
+	| declaration_list declaration
+		{ $$ = $1->set_last( $2 ); }
 	;
 
@@ -1910,5 +1910,5 @@
 		{ $$ = $1; }
 	| KR_parameter_list c_declaration ';'
-		{ $$ = $1->appendList( $2 ); }
+		{ $$ = $1->set_last( $2 ); }
 	;
 
@@ -1968,5 +1968,5 @@
 		{ $$ = $2->addQualifiers( $1 )->addInitializer( $3 ); }
 	| cfa_variable_declaration pop ',' push identifier_or_type_name initializer_opt
-		{ $$ = $1->appendList( $1->cloneType( $5 )->addInitializer( $6 ) ); }
+		{ $$ = $1->set_last( $1->cloneType( $5 )->addInitializer( $6 ) ); }
 	;
 
@@ -1990,40 +1990,32 @@
 	| declaration_qualifier_list type_qualifier_list cfa_function_specifier
 		{ $$ = $3->addQualifiers( $1 )->addQualifiers( $2 ); }
-	| cfa_function_declaration ',' identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')'
+	| cfa_function_declaration ',' identifier_or_type_name '(' push cfa_parameter_list_ellipsis_opt pop ')'
 		{
 			// Append the return type at the start (left-hand-side) to each identifier in the list.
 			DeclarationNode * ret = new DeclarationNode;
 			ret->type = maybeCopy( $1->type->base );
-			$$ = $1->appendList( DeclarationNode::newFunction( $3, ret, $6, nullptr ) );
+			$$ = $1->set_last( DeclarationNode::newFunction( $3, ret, $6, nullptr ) );
 		}
 	;
 
 cfa_function_specifier:									// CFA
-//	'[' ']' identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' // S/R conflict
-//		{
-//			$$ = DeclarationNode::newFunction( $3, DeclarationNode::newTuple( 0 ), $6, nullptr, true );
-//		}
-//	'[' ']' identifier '(' push cfa_parameter_ellipsis_list_opt pop ')'
-//		{
-//			typedefTable.setNextIdentifier( *$5 );
-//			$$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, nullptr, true );
-//		}
-//	| '[' ']' TYPEDEFname '(' push cfa_parameter_ellipsis_list_opt pop ')'
-//		{
-//			typedefTable.setNextIdentifier( *$5 );
-//			$$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, nullptr, true );
-//		}
-//	| '[' ']' typegen_name
+	'[' ']' identifier '(' push cfa_parameter_list_ellipsis_opt pop ')' attribute_list_opt
+		{ $$ = DeclarationNode::newFunction( $3,  DeclarationNode::newTuple( nullptr ), $6, nullptr )->addQualifiers( $9 ); }
+	| '[' ']' TYPEDEFname '(' push cfa_parameter_list_ellipsis_opt pop ')' attribute_list_opt
+		{ $$ = DeclarationNode::newFunction( $3,  DeclarationNode::newTuple( nullptr ), $6, nullptr )->addQualifiers( $9 ); }
+	// | '[' ']' TYPEGENname '(' push cfa_parameter_list_ellipsis_opt pop ')' attribute_list_opt
+	// 	{ $$ = DeclarationNode::newFunction( $3,  DeclarationNode::newTuple( nullptr ), $6, nullptr )->addQualifiers( $9 ); }
+
 		// identifier_or_type_name must be broken apart because of the sequence:
 		//
-		//   '[' ']' identifier_or_type_name '(' cfa_parameter_ellipsis_list_opt ')'
+		//   '[' ']' identifier_or_type_name '(' cfa_parameter_list_ellipsis_opt ')'
 		//   '[' ']' type_specifier
 		//
 		// type_specifier can resolve to just TYPEDEFname (e.g., typedef int T; int f( T );). Therefore this must be
 		// flattened to allow lookahead to the '(' without having to reduce identifier_or_type_name.
-	cfa_abstract_tuple identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' attribute_list_opt
+	| cfa_abstract_tuple identifier_or_type_name '(' push cfa_parameter_list_ellipsis_opt pop ')' attribute_list_opt
 		// To obtain LR(1 ), this rule must be factored out from function return type (see cfa_abstract_declarator).
 		{ $$ = DeclarationNode::newFunction( $2, $1, $5, nullptr )->addQualifiers( $8 ); }
-	| cfa_function_return identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' attribute_list_opt
+	| cfa_function_return identifier_or_type_name '(' push cfa_parameter_list_ellipsis_opt pop ')' attribute_list_opt
 		{ $$ = DeclarationNode::newFunction( $2, $1, $5, nullptr )->addQualifiers( $8 ); }
 	;
@@ -2032,7 +2024,7 @@
 	'[' push cfa_parameter_list pop ']'
 		{ $$ = DeclarationNode::newTuple( $3 ); }
-	| '[' push cfa_parameter_list pop ',' push cfa_abstract_parameter_list pop ']'
+	| '[' push cfa_parameter_list ',' cfa_abstract_parameter_list pop ']'
 		// To obtain LR(1 ), the last cfa_abstract_parameter_list is added into this flattened rule to lookahead to the ']'.
-		{ $$ = DeclarationNode::newTuple( $3->appendList( $7 ) ); }
+		{ $$ = DeclarationNode::newTuple( $3->set_last( $5 ) ); }
 	;
 
@@ -2048,8 +2040,8 @@
 			$$ = $2->addTypedef();
 		}
-	| cfa_typedef_declaration pop ',' push identifier
-		{
-			typedefTable.addToEnclosingScope( *$5, TYPEDEFname, "cfa_typedef_declaration 3" );
-			$$ = $1->appendList( $1->cloneType( $5 ) );
+	| cfa_typedef_declaration ',' identifier
+		{
+			typedefTable.addToEnclosingScope( *$3, TYPEDEFname, "cfa_typedef_declaration 3" );
+			$$ = $1->set_last( $1->cloneType( $3 ) );
 		}
 	;
@@ -2069,5 +2061,5 @@
 		{
 			typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname, "typedef_declaration 2" );
-			$$ = $1->appendList( $1->cloneBaseType( $3 )->addTypedef() );
+			$$ = $1->set_last( $1->cloneBaseType( $3 )->addTypedef() );
 		}
 	| type_qualifier_list TYPEDEF type_specifier declarator // remaining OBSOLESCENT (see 2 )
@@ -2123,5 +2115,5 @@
 
 	| declaring_list ',' attribute_list_opt declarator asm_name_opt initializer_opt
-		{ $$ = $1->appendList( $4->addQualifiers( $3 )->addAsmName( $5 )->addInitializer( $6 ) ); }
+		{ $$ = $1->set_last( $4->addQualifiers( $3 )->addAsmName( $5 )->addInitializer( $6 ) ); }
 	;
 
@@ -2587,5 +2579,5 @@
 		{ $$ = nullptr; }
 	| field_declaration_list_opt field_declaration
-		{ $$ = $1 ? $1->appendList( $2 ) : $2; }
+		{ $$ = $1 ? $1->set_last( $2 ) : $2; }
 	;
 
@@ -2635,5 +2627,5 @@
 	| field_declarator
 	| field_declaring_list_opt ',' attribute_list_opt field_declarator
-		{ $$ = $1->appendList( $4->addQualifiers( $3 ) ); }
+		{ $$ = $1->set_last( $4->addQualifiers( $3 ) ); }
 	;
 
@@ -2657,5 +2649,5 @@
 	| field_abstract
 	| field_abstract_list_opt ',' attribute_list_opt field_abstract
-		{ $$ = $1->appendList( $4->addQualifiers( $3 ) ); }
+		{ $$ = $1->set_last( $4->addQualifiers( $3 ) ); }
 	;
 
@@ -2670,5 +2662,5 @@
 		{ $$ = $1->addName( $2 ); }
 	| cfa_field_declaring_list ',' identifier_or_type_name
-		{ $$ = $1->appendList( $1->cloneType( $3 ) ); }
+		{ $$ = $1->set_last( $1->cloneType( $3 ) ); }
 	;
 
@@ -2677,5 +2669,5 @@
 	cfa_abstract_declarator_tuple
 	| cfa_field_abstract_list ','
-		{ $$ = $1->appendList( $1->cloneType( 0 ) ); }
+		{ $$ = $1->set_last( $1->cloneType( 0 ) ); }
 	;
 
@@ -2690,4 +2682,8 @@
 		{ $$ = $2; }
 	;
+
+// ***********
+// Enumeration
+// ***********
 
 enum_type:
@@ -2719,5 +2715,5 @@
 	| ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt identifier attribute_list_opt
 		{
-			if ( $3 && ($3->storageClasses.any() || $3->type->qualifiers.val != 0 )) {
+			if ( $3 && ($3->storageClasses.any() || $3->type->qualifiers.val != 0) ) {
 				SemanticError( yylloc, "syntax error, storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." );
 			}
@@ -2769,7 +2765,7 @@
 		{ $$ = DeclarationNode::newEnumInLine( *$2->type->symbolic.name ); }
 	| enumerator_list ',' visible_hide_opt identifier_or_type_name enumerator_value_opt
-		{ $$ = $1->appendList( DeclarationNode::newEnumValueGeneric( $4, $5 ) ); }
+		{ $$ = $1->set_last( DeclarationNode::newEnumValueGeneric( $4, $5 ) ); }
 	| enumerator_list ',' INLINE type_name enumerator_value_opt
-		{ $$ = $1->appendList( DeclarationNode::newEnumValueGeneric( new string("inline"), nullptr ) ); }
+		{ $$ = $1->set_last( DeclarationNode::newEnumValueGeneric( new string("inline"), nullptr ) ); }
 	;
 
@@ -2789,38 +2785,9 @@
 	;
 
-cfa_parameter_ellipsis_list_opt:						// CFA, abstract + real
-	// empty
-		{ $$ = DeclarationNode::newBasicType( DeclarationNode::Void ); }
-	| ELLIPSIS
-		{ $$ = nullptr; }
-	| cfa_abstract_parameter_list
-	| cfa_parameter_list
-	| cfa_parameter_list pop ',' push cfa_abstract_parameter_list
-		{ $$ = $1->appendList( $5 ); }
-	| cfa_abstract_parameter_list pop ',' push ELLIPSIS
-		{ $$ = $1->addVarArgs(); }
-	| cfa_parameter_list pop ',' push ELLIPSIS
-		{ $$ = $1->addVarArgs(); }
-	;
-
-cfa_parameter_list:										// CFA
-		// To obtain LR(1) between cfa_parameter_list and cfa_abstract_tuple, the last cfa_abstract_parameter_list is
-		// factored out from cfa_parameter_list, flattening the rules to get lookahead to the ']'.
-	cfa_parameter_declaration
-	| cfa_abstract_parameter_list pop ',' push cfa_parameter_declaration
-		{ $$ = $1->appendList( $5 ); }
-	| cfa_parameter_list pop ',' push cfa_parameter_declaration
-		{ $$ = $1->appendList( $5 ); }
-	| cfa_parameter_list pop ',' push cfa_abstract_parameter_list pop ',' push cfa_parameter_declaration
-		{ $$ = $1->appendList( $5 )->appendList( $9 ); }
-	;
-
-cfa_abstract_parameter_list:							// CFA, new & old style abstract
-	cfa_abstract_parameter_declaration
-	| cfa_abstract_parameter_list pop ',' push cfa_abstract_parameter_declaration
-		{ $$ = $1->appendList( $5 ); }
-	;
-
-parameter_type_list_opt:
+// *******************
+// Function parameters
+// *******************
+
+parameter_list_ellipsis_opt:
 	// empty
 		{ $$ = nullptr; }
@@ -2833,14 +2800,62 @@
 
 parameter_list:											// abstract + real
-	abstract_parameter_declaration
-	| parameter_declaration
+	parameter_declaration
+	| abstract_parameter_declaration
+	| parameter_list ',' parameter_declaration
+		{ $$ = $1->set_last( $3 ); }
 	| parameter_list ',' abstract_parameter_declaration
-		{ $$ = $1->appendList( $3 ); }
-	| parameter_list ',' parameter_declaration
-		{ $$ = $1->appendList( $3 ); }
+		{ $$ = $1->set_last( $3 ); }
+	;
+
+cfa_parameter_list_ellipsis_opt:						// CFA, abstract + real
+	// empty
+		{ $$ = DeclarationNode::newBasicType( DeclarationNode::Void ); }
+	| ELLIPSIS
+		{ $$ = nullptr; }
+	| cfa_parameter_list
+	| cfa_abstract_parameter_list
+	| cfa_parameter_list ',' cfa_abstract_parameter_list
+		{ $$ = $1->set_last( $3 ); }
+	| cfa_parameter_list ',' ELLIPSIS
+		{ $$ = $1->addVarArgs(); }
+	| cfa_abstract_parameter_list ',' ELLIPSIS
+		{ $$ = $1->addVarArgs(); }
+	;
+
+cfa_parameter_list:										// CFA
+		// To obtain LR(1) between cfa_parameter_list and cfa_abstract_tuple, the last cfa_abstract_parameter_list is
+		// factored out from cfa_parameter_list, flattening the rules to get lookahead to the ']'.
+	cfa_parameter_declaration
+	| cfa_abstract_parameter_list ',' cfa_parameter_declaration
+		{ $$ = $1->set_last( $3 ); }
+	| cfa_parameter_list ',' cfa_parameter_declaration
+		{ $$ = $1->set_last( $3 ); }
+	| cfa_parameter_list ',' cfa_abstract_parameter_list ',' cfa_parameter_declaration
+		{ $$ = $1->set_last( $3 )->set_last( $5 ); }
+	;
+
+cfa_abstract_parameter_list:							// CFA, new & old style abstract
+	cfa_abstract_parameter_declaration
+	| cfa_abstract_parameter_list ',' cfa_abstract_parameter_declaration
+		{ $$ = $1->set_last( $3 ); }
 	;
 
 // Provides optional identifier names (abstract_declarator/variable_declarator), no initialization, different semantics
 // for typedef name by using type_parameter_redeclarator instead of typedef_redeclarator, and function prototypes.
+
+parameter_declaration:
+		// No SUE declaration in parameter list.
+	declaration_specifier_nobody identifier_parameter_declarator default_initializer_opt
+		{ $$ = $2->addType( $1 )->addInitializer( $3 ? new InitializerNode( $3 ) : nullptr ); }
+	| declaration_specifier_nobody type_parameter_redeclarator default_initializer_opt
+		{ $$ = $2->addType( $1 )->addInitializer( $3 ? new InitializerNode( $3 ) : nullptr ); }
+	;
+
+abstract_parameter_declaration:
+	declaration_specifier_nobody default_initializer_opt
+		{ $$ = $1->addInitializer( $2 ? new InitializerNode( $2 ) : nullptr ); }
+	| declaration_specifier_nobody abstract_parameter_declarator default_initializer_opt
+		{ $$ = $2->addType( $1 )->addInitializer( $3 ? new InitializerNode( $3 ) : nullptr ); }
+	;
 
 cfa_parameter_declaration:								// CFA, new & old style parameter declaration
@@ -2866,19 +2881,4 @@
 	;
 
-parameter_declaration:
-		// No SUE declaration in parameter list.
-	declaration_specifier_nobody identifier_parameter_declarator default_initializer_opt
-		{ $$ = $2->addType( $1 )->addInitializer( $3 ? new InitializerNode( $3 ) : nullptr ); }
-	| declaration_specifier_nobody type_parameter_redeclarator default_initializer_opt
-		{ $$ = $2->addType( $1 )->addInitializer( $3 ? new InitializerNode( $3 ) : nullptr ); }
-	;
-
-abstract_parameter_declaration:
-	declaration_specifier_nobody default_initializer_opt
-		{ $$ = $1->addInitializer( $2 ? new InitializerNode( $2 ) : nullptr ); }
-	| declaration_specifier_nobody abstract_parameter_declarator default_initializer_opt
-		{ $$ = $2->addType( $1 )->addInitializer( $3 ? new InitializerNode( $3 ) : nullptr ); }
-	;
-
 // ISO/IEC 9899:1999 Section 6.9.1(6) : "An identifier declared as a typedef name shall not be redeclared as a
 // parameter." Because the scope of the K&R-style parameter-list sees the typedef first, the following is based only on
@@ -2889,5 +2889,5 @@
 		{ $$ = DeclarationNode::newName( $1 ); }
 	| identifier_list ',' identifier
-		{ $$ = $1->appendList( DeclarationNode::newName( $3 ) ); }
+		{ $$ = $1->set_last( DeclarationNode::newName( $3 ) ); }
 	;
 
@@ -2990,5 +2990,5 @@
 	type_parameter
 	| type_parameter_list ',' type_parameter
-		{ $$ = $1->appendList( $3 ); }
+		{ $$ = $1->set_last( $3 ); }
 	;
 
@@ -3063,5 +3063,5 @@
 	assertion
 	| assertion_list assertion
-		{ $$ = $1->appendList( $2 ); }
+		{ $$ = $1->set_last( $2 ); }
 	;
 
@@ -3091,5 +3091,5 @@
 		{ $$ = $3->addQualifiers( $1 ); }
 	| type_declaring_list ',' type_declarator
-		{ $$ = $1->appendList( $3->copySpecifiers( $1 ) ); }
+		{ $$ = $1->set_last( $3->copySpecifiers( $1 ) ); }
 	;
 
@@ -3134,5 +3134,5 @@
 	trait_declaration
 	| trait_declaration_list pop push trait_declaration
-		{ $$ = $1->appendList( $4 ); }
+		{ $$ = $1->set_last( $4 ); }
 	;
 
@@ -3146,5 +3146,5 @@
 	| cfa_function_specifier
 	| cfa_trait_declaring_list pop ',' push identifier_or_type_name
-		{ $$ = $1->appendList( $1->cloneType( $5 ) ); }
+		{ $$ = $1->set_last( $1->cloneType( $5 ) ); }
 	;
 
@@ -3153,5 +3153,5 @@
 		{ $$ = $2->addType( $1 ); }
 	| trait_declaring_list pop ',' push declarator
-		{ $$ = $1->appendList( $1->cloneBaseType( $5 ) ); }
+		{ $$ = $1->set_last( $1->cloneBaseType( $5 ) ); }
 	;
 
@@ -3161,5 +3161,5 @@
 	// empty, input file
 	| external_definition_list
-		{ parseTree = parseTree ? parseTree->appendList( $1 ) : $1;	}
+		{ parseTree = parseTree ? parseTree->set_last( $1 ) : $1;	}
 	;
 
@@ -3168,5 +3168,5 @@
 		{ $$ = $2; }
 	| external_definition_list push external_definition pop
-		{ $$ = $1 ? $1->appendList( $3 ) : $3; }
+		{ $$ = $1 ? $1->set_last( $3 ) : $3; }
 	;
 
@@ -3395,4 +3395,8 @@
 	ATTRIBUTE '(' '(' attribute_name_list ')' ')'
 		{ $$ = $4; }
+	| ATTRIBUTE '(' attribute_name_list ')'				// CFA
+		{ $$ = $3; }
+	| ATTR '(' attribute_name_list ')'					// CFA
+		{ $$ = $3; }
 	;
 
@@ -3499,7 +3503,7 @@
 
 variable_function:
-	'(' variable_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
+	'(' variable_ptr ')' '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
 		{ $$ = $2->addParamList( $5 ); }
-	| '(' attribute_list variable_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
+	| '(' attribute_list variable_ptr ')' '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
 		{ $$ = $3->addQualifiers( $2 )->addParamList( $6 ); }
 	| '(' variable_function ')'							// redundant parenthesis
@@ -3522,9 +3526,9 @@
 
 function_no_ptr:
-	paren_identifier '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
+	paren_identifier '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
 		{ $$ = $1->addParamList( $3 ); }
-	| '(' function_ptr ')' '(' parameter_type_list_opt ')'
+	| '(' function_ptr ')' '(' parameter_list_ellipsis_opt ')'
 		{ $$ = $2->addParamList( $5 ); }
-	| '(' attribute_list function_ptr ')' '(' parameter_type_list_opt ')'
+	| '(' attribute_list function_ptr ')' '(' parameter_list_ellipsis_opt ')'
 		{ $$ = $3->addQualifiers( $2 )->addParamList( $6 ); }
 	| '(' function_no_ptr ')'							// redundant parenthesis
@@ -3576,7 +3580,7 @@
 	paren_identifier '(' identifier_list ')'			// function_declarator handles empty parameter
 		{ $$ = $1->addIdList( $3 ); }
-	| '(' KR_function_ptr ')' '(' parameter_type_list_opt ')'
+	| '(' KR_function_ptr ')' '(' parameter_list_ellipsis_opt ')'
 		{ $$ = $2->addParamList( $5 ); }
-	| '(' attribute_list KR_function_ptr ')' '(' parameter_type_list_opt ')'
+	| '(' attribute_list KR_function_ptr ')' '(' parameter_list_ellipsis_opt ')'
 		{ $$ = $3->addQualifiers( $2 )->addParamList( $6 ); }
 	| '(' KR_function_no_ptr ')'						// redundant parenthesis
@@ -3668,7 +3672,7 @@
 
 variable_type_function:
-	'(' variable_type_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
+	'(' variable_type_ptr ')' '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
 		{ $$ = $2->addParamList( $5 ); }
-	| '(' attribute_list variable_type_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
+	| '(' attribute_list variable_type_ptr ')' '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
 		{ $$ = $3->addQualifiers( $2 )->addParamList( $6 ); }
 	| '(' variable_type_function ')'					// redundant parenthesis
@@ -3691,9 +3695,9 @@
 
 function_type_no_ptr:
-	paren_type '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
+	paren_type '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
 		{ $$ = $1->addParamList( $3 ); }
-	| '(' function_type_ptr ')' '(' parameter_type_list_opt ')'
+	| '(' function_type_ptr ')' '(' parameter_list_ellipsis_opt ')'
 		{ $$ = $2->addParamList( $5 ); }
-	| '(' attribute_list function_type_ptr ')' '(' parameter_type_list_opt ')'
+	| '(' attribute_list function_type_ptr ')' '(' parameter_list_ellipsis_opt ')'
 		{ $$ = $3->addQualifiers( $2 )->addParamList( $6 ); }
 	| '(' function_type_no_ptr ')'						// redundant parenthesis
@@ -3738,5 +3742,6 @@
 		{ $$ = $1->addQualifiers( $2 ); }
 	| '&' MUTEX paren_identifier attribute_list_opt
-		{ $$ = $3->addPointer( DeclarationNode::newPointer( DeclarationNode::newTypeQualifier( ast::CV::Mutex ), OperKinds::AddressOf ) )->addQualifiers( $4 ); }
+		{ $$ = $3->addPointer( DeclarationNode::newPointer( DeclarationNode::newTypeQualifier( ast::CV::Mutex ),
+															OperKinds::AddressOf ) )->addQualifiers( $4 ); }
 	| identifier_parameter_ptr
 	| identifier_parameter_array attribute_list_opt
@@ -3767,7 +3772,7 @@
 
 identifier_parameter_function:
-	paren_identifier '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
+	paren_identifier '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
 		{ $$ = $1->addParamList( $3 ); }
-	| '(' identifier_parameter_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
+	| '(' identifier_parameter_ptr ')' '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
 		{ $$ = $2->addParamList( $5 ); }
 	| '(' identifier_parameter_function ')'				// redundant parenthesis
@@ -3788,5 +3793,6 @@
 		{ $$ = $1->addQualifiers( $2 ); }
 	| '&' MUTEX typedef_name attribute_list_opt
-		{ $$ = $3->addPointer( DeclarationNode::newPointer( DeclarationNode::newTypeQualifier( ast::CV::Mutex ), OperKinds::AddressOf ) )->addQualifiers( $4 ); }
+		{ $$ = $3->addPointer( DeclarationNode::newPointer( DeclarationNode::newTypeQualifier( ast::CV::Mutex ),
+															OperKinds::AddressOf ) )->addQualifiers( $4 ); }
 	| type_parameter_ptr
 	| type_parameter_array attribute_list_opt
@@ -3820,7 +3826,7 @@
 
 type_parameter_function:
-	typedef_name '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
+	typedef_name '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
 		{ $$ = $1->addParamList( $3 ); }
-	| '(' type_parameter_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
+	| '(' type_parameter_ptr ')' '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
 		{ $$ = $2->addParamList( $5 ); }
 	;
@@ -3870,7 +3876,7 @@
 
 abstract_function:
-	'(' parameter_type_list_opt ')'			// empty parameter list OBSOLESCENT (see 3)
+	'(' parameter_list_ellipsis_opt ')'			// empty parameter list OBSOLESCENT (see 3)
 		{ $$ = DeclarationNode::newFunction( nullptr, nullptr, $2, nullptr ); }
-	| '(' abstract_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
+	| '(' abstract_ptr ')' '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
 		{ $$ = $2->addParamList( $5 ); }
 	| '(' abstract_function ')'							// redundant parenthesis
@@ -3888,8 +3894,17 @@
 		{ $$ = DeclarationNode::newArray( $3, nullptr, false )->addArray( DeclarationNode::newArray( $6, nullptr, false ) ); }
 		// { SemanticError( yylloc, "New array dimension is currently unimplemented." ); $$ = nullptr; }
+
+		// If needed, the following parses and does not use comma_expression, so the array structure can be built.
+	// | '[' push assignment_expression pop ',' push array_dimension_list pop ']' // CFA
+
 	| '[' push array_type_list pop ']'					// CFA
 		{ $$ = DeclarationNode::newArray( $3, nullptr, false ); }
 	| multi_array_dimension
 	;
+
+// array_dimension_list:
+// 	assignment_expression
+// 	| array_dimension_list ',' assignment_expression
+// 	;
 
 array_type_list:
@@ -3993,7 +4008,7 @@
 
 abstract_parameter_function:
-	'(' parameter_type_list_opt ')'			// empty parameter list OBSOLESCENT (see 3)
+	'(' parameter_list_ellipsis_opt ')'			// empty parameter list OBSOLESCENT (see 3)
 		{ $$ = DeclarationNode::newFunction( nullptr, nullptr, $2, nullptr ); }
-	| '(' abstract_parameter_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
+	| '(' abstract_parameter_ptr ')' '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
 		{ $$ = $2->addParamList( $5 ); }
 	| '(' abstract_parameter_function ')'				// redundant parenthesis
@@ -4072,5 +4087,5 @@
 
 variable_abstract_function:
-	'(' variable_abstract_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
+	'(' variable_abstract_ptr ')' '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
 		{ $$ = $2->addParamList( $5 ); }
 	| '(' variable_abstract_function ')'				// redundant parenthesis
@@ -4158,5 +4173,5 @@
 //
 //		cfa_abstract_tuple identifier_or_type_name
-//		'[' cfa_parameter_list ']' identifier_or_type_name '(' cfa_parameter_ellipsis_list_opt ')'
+//		'[' cfa_parameter_list ']' identifier_or_type_name '(' cfa_parameter_list_ellipsis_opt ')'
 //
 // since a function return type can be syntactically identical to a tuple type:
@@ -4224,9 +4239,9 @@
 
 cfa_abstract_function:									// CFA
-//	'[' ']' '(' cfa_parameter_ellipsis_list_opt ')'
-//		{ $$ = DeclarationNode::newFunction( nullptr, DeclarationNode::newTuple( nullptr ), $4, nullptr ); }
-	cfa_abstract_tuple '(' push cfa_parameter_ellipsis_list_opt pop ')'
+	'[' ']' '(' cfa_parameter_list_ellipsis_opt ')'
+		{ $$ = DeclarationNode::newFunction( nullptr, DeclarationNode::newTuple( nullptr ), $4, nullptr ); }
+	| cfa_abstract_tuple '(' push cfa_parameter_list_ellipsis_opt pop ')'
 		{ $$ = DeclarationNode::newFunction( nullptr, $1, $4, nullptr ); }
-	| cfa_function_return '(' push cfa_parameter_ellipsis_list_opt pop ')'
+	| cfa_function_return '(' push cfa_parameter_list_ellipsis_opt pop ')'
 		{ $$ = DeclarationNode::newFunction( nullptr, $1, $4, nullptr ); }
 	;
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision bbf2cb164e26be1589f185df9bf81b21c503c1d2)
+++ src/ResolvExpr/Resolver.cc	(revision f6e8c672a67785468988dfd68943c378679cbddf)
@@ -412,4 +412,5 @@
 
 	void resolveWithExprs(std::vector<ast::ptr<ast::Expr>> & exprs, std::list<ast::ptr<ast::Stmt>> & stmtsToAdd);
+	bool shouldGenCtorInit( const ast::ObjectDecl * ) const;
 
 	void beginScope() { managedTypes.beginScope(); }
@@ -581,4 +582,15 @@
 }
 
+bool Resolver::shouldGenCtorInit( ast::ObjectDecl const * decl ) const {
+	// If we shouldn't try to construct it, then don't.
+	if ( !InitTweak::tryConstruct( decl ) ) return false;
+	// Otherwise, if it is a managed type, we may construct it.
+	if ( managedTypes.isManaged( decl ) ) return true;
+	// Skip construction if it is trivial at compile-time.
+	if ( InitTweak::isConstExpr( decl->init ) ) return false;
+	// Skip construction for local declarations.
+	return ( !isInFunction() || decl->storage.is_static );
+}
+
 const ast::ObjectDecl * Resolver::previsit( const ast::ObjectDecl * objectDecl ) {
 	// To handle initialization of routine pointers [e.g. int (*fp)(int) = foo()],
@@ -615,5 +627,5 @@
 			// this object in visitor pass, thus disabling CtorInit codegen.
 			// this happens on aggregate members and function parameters.
-			if ( InitTweak::tryConstruct( mutDecl ) && ( managedTypes.isManaged( mutDecl ) || ((! isInFunction() || mutDecl->storage.is_static ) && ! InitTweak::isConstExpr( mutDecl->init ) ) ) ) {
+			if ( shouldGenCtorInit( mutDecl ) ) {
 				// constructed objects cannot be designated
 				if ( InitTweak::isDesignated( mutDecl->init ) ) {
