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;
