Index: src/Parser/DeclarationNode.cc
===================================================================
--- src/Parser/DeclarationNode.cc	(revision 44adf1b408dc3453ae636391512592322192a1da)
+++ src/Parser/DeclarationNode.cc	(revision af603836967459bc39bcd5b1d600361e31956593)
@@ -104,5 +104,4 @@
 	newnode->name = name ? new string( *name ) : nullptr;
 
-	newnode->builtin = NoBuiltinType;
 	newnode->type = maybeCopy( type );
 	newnode->inLine = inLine;
@@ -435,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
@@ -556,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
@@ -582,26 +569,11 @@
 	} // if
 
-	if ( q->type->forall ) {							// forall qualifier ?
-		if ( type->forall ) {							// polymorphic routine ?
-			type->forall->set_last( q->type->forall ); // augment forall qualifier
-		} else {
-			if ( type->kind == TypeData::Aggregate ) {	// struct/union ?
-				if ( type->aggregate.params ) {			// polymorphic ?
-					type->aggregate.params->set_last( 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;
@@ -609,124 +581,29 @@
 } // addQualifiers
 
-static void addTypeToType( TypeData *& src, TypeData *& dst ) {
-	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( 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->set_last( 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->next ) {
-			set_last( o->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;
@@ -812,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;
@@ -859,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
@@ -882,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
@@ -962,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;
Index: src/Parser/DeclarationNode.h
===================================================================
--- src/Parser/DeclarationNode.h	(revision 44adf1b408dc3453ae636391512592322192a1da)
+++ src/Parser/DeclarationNode.h	(revision af603836967459bc39bcd5b1d600361e31956593)
@@ -141,6 +141,4 @@
 	StaticAssert_t assert;
 
-	BuiltinType builtin = NoBuiltinType;
-
 	TypeData * type = nullptr;
 
Index: src/Parser/TypeData.cc
===================================================================
--- src/Parser/TypeData.cc	(revision 44adf1b408dc3453ae636391512592322192a1da)
+++ src/Parser/TypeData.cc	(revision af603836967459bc39bcd5b1d600361e31956593)
@@ -476,4 +476,200 @@
 	} // switch
 	assert(false);
+}
+
+
+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
 }
 
Index: src/Parser/TypeData.h
===================================================================
--- src/Parser/TypeData.h	(revision 44adf1b408dc3453ae636391512592322192a1da)
+++ src/Parser/TypeData.h	(revision af603836967459bc39bcd5b1d600361e31956593)
@@ -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 * );
