Index: src/CodeGen/CodeGenerator.cc
===================================================================
--- src/CodeGen/CodeGenerator.cc	(revision bbe1a87944804b0f3c9e486087ca6af21340e747)
+++ src/CodeGen/CodeGenerator.cc	(revision e3b24743580e0faaf833a980c334820f77cfefaf)
@@ -164,5 +164,5 @@
 		previsit( (BaseSyntaxNode *)node );
 		GuardAction( [this, node](){
-			if ( printExprTypes ) {
+			if ( printExprTypes && node->result ) {
 				output << " /* " << genType( node->result, "", pretty, genC ) << " */ ";
 			}
@@ -224,8 +224,8 @@
 
 	void CodeGenerator::handleAggregate( AggregateDecl * aggDecl, const std::string & kind ) {
-		if( ! aggDecl->get_parameters().empty() && ! genC ) {
+		if( ! aggDecl->parameters.empty() && ! genC ) {
 			// assertf( ! genC, "Aggregate type parameters should not reach code generation." );
 			output << "forall(";
-			genCommaList( aggDecl->get_parameters().begin(), aggDecl->get_parameters().end() );
+			genCommaList( aggDecl->parameters.begin(), aggDecl->parameters.end() );
 			output << ")" << endl;
 			output << indent;
@@ -233,9 +233,9 @@
 
 		output << kind;
-		genAttributes( aggDecl->get_attributes() );
-		output << aggDecl->get_name();
+		genAttributes( aggDecl->attributes );
+		output << aggDecl->name;
 
 		if ( aggDecl->has_body() ) {
-			std::list< Declaration * > & memb = aggDecl->get_members();
+			std::list< Declaration * > & memb = aggDecl->members;
 			output << " {" << endl;
 
Index: src/CodeGen/GenType.cc
===================================================================
--- src/CodeGen/GenType.cc	(revision bbe1a87944804b0f3c9e486087ca6af21340e747)
+++ src/CodeGen/GenType.cc	(revision e3b24743580e0faaf833a980c334820f77cfefaf)
@@ -48,6 +48,8 @@
 		void postvisit( ZeroType * zeroType );
 		void postvisit( OneType * oneType );
+		void postvisit( GlobalScopeType * globalType );
 		void postvisit( TraitInstType * inst );
 		void postvisit( TypeofType * typeof );
+		void postvisit( QualifiedType * qualType );
 
 	  private:
@@ -291,4 +293,9 @@
 	}
 
+	void GenType::postvisit( GlobalScopeType * globalType ) {
+		assertf( ! genC, "Global scope type should not reach code generation." );
+		handleQualifiers( globalType );
+	}
+
 	void GenType::postvisit( TraitInstType * inst ) {
 		assertf( ! genC, "Trait types should not reach code generation." );
@@ -307,4 +314,12 @@
 	}
 
+	void GenType::postvisit( QualifiedType * qualType ) {
+		assertf( ! genC, "Qualified types should not reach code generation." );
+		std::ostringstream os;
+		os << genType( qualType->parent, "", pretty, genC, lineMarks ) << "." << genType( qualType->child, "", pretty, genC, lineMarks ) << typeString;
+		typeString = os.str();
+		handleQualifiers( qualType );
+	}
+
 	void GenType::handleQualifiers( Type * type ) {
 		if ( type->get_const() ) {
Index: src/Common/PassVisitor.h
===================================================================
--- src/Common/PassVisitor.h	(revision bbe1a87944804b0f3c9e486087ca6af21340e747)
+++ src/Common/PassVisitor.h	(revision e3b24743580e0faaf833a980c334820f77cfefaf)
@@ -133,4 +133,5 @@
 	virtual void visit( ArrayType * arrayType ) override final;
 	virtual void visit( ReferenceType * referenceType ) override final;
+	virtual void visit( QualifiedType * qualType ) override final;
 	virtual void visit( FunctionType * functionType ) override final;
 	virtual void visit( StructInstType * aggregateUseType ) override final;
@@ -145,4 +146,5 @@
 	virtual void visit( ZeroType * zeroType ) override final;
 	virtual void visit( OneType * oneType ) override final;
+	virtual void visit( GlobalScopeType * globalType ) override final;
 
 	virtual void visit( Designation * designation ) override final;
@@ -233,4 +235,5 @@
 	virtual Type * mutate( ArrayType * arrayType ) override final;
 	virtual Type * mutate( ReferenceType * referenceType ) override final;
+	virtual Type * mutate( QualifiedType * qualType ) override final;
 	virtual Type * mutate( FunctionType * functionType ) override final;
 	virtual Type * mutate( StructInstType * aggregateUseType ) override final;
@@ -245,4 +248,5 @@
 	virtual Type * mutate( ZeroType * zeroType ) override final;
 	virtual Type * mutate( OneType * oneType ) override final;
+	virtual Type * mutate( GlobalScopeType * globalType ) override final;
 
 	virtual Designation * mutate( Designation * designation ) override final;
Index: src/Common/PassVisitor.impl.h
===================================================================
--- src/Common/PassVisitor.impl.h	(revision bbe1a87944804b0f3c9e486087ca6af21340e747)
+++ src/Common/PassVisitor.impl.h	(revision e3b24743580e0faaf833a980c334820f77cfefaf)
@@ -2262,4 +2262,28 @@
 
 //--------------------------------------------------------------------------
+// QualifiedType
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( QualifiedType * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->forall, *this );
+	maybeAccept_impl( node->parent, *this );
+	maybeAccept_impl( node->child, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Type * PassVisitor< pass_type >::mutate( QualifiedType * node ) {
+	MUTATE_START( node );
+
+	maybeMutate_impl( node->forall, *this );
+	maybeMutate_impl( node->parent, *this );
+	maybeMutate_impl( node->child, *this );
+
+	MUTATE_END( Type, node );
+}
+
+//--------------------------------------------------------------------------
 // FunctionType
 template< typename pass_type >
@@ -2554,4 +2578,24 @@
 
 //--------------------------------------------------------------------------
+// GlobalScopeType
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( GlobalScopeType * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->forall, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Type * PassVisitor< pass_type >::mutate( GlobalScopeType * node ) {
+	MUTATE_START( node );
+
+	maybeMutate_impl( node->forall, *this );
+
+	MUTATE_END( Type, node );
+}
+
+//--------------------------------------------------------------------------
 // Designation
 template< typename pass_type >
Index: src/Concurrency/Keywords.cc
===================================================================
--- src/Concurrency/Keywords.cc	(revision bbe1a87944804b0f3c9e486087ca6af21340e747)
+++ src/Concurrency/Keywords.cc	(revision e3b24743580e0faaf833a980c334820f77cfefaf)
@@ -501,13 +501,13 @@
 	void MutexKeyword::postvisit(StructDecl* decl) {
 
-		if( decl->name == "monitor_desc" ) {
+		if( decl->name == "monitor_desc" && decl->body ) {
 			assert( !monitor_decl );
 			monitor_decl = decl;
 		}
-		else if( decl->name == "monitor_guard_t" ) {
+		else if( decl->name == "monitor_guard_t" && decl->body ) {
 			assert( !guard_decl );
 			guard_decl = decl;
 		}
-		else if( decl->name == "monitor_dtor_guard_t" ) {
+		else if( decl->name == "monitor_dtor_guard_t" && decl->body ) {
 			assert( !dtor_guard_decl );
 			dtor_guard_decl = decl;
Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision bbe1a87944804b0f3c9e486087ca6af21340e747)
+++ src/InitTweak/FixInit.cc	(revision e3b24743580e0faaf833a980c334820f77cfefaf)
@@ -1163,7 +1163,7 @@
 
 			std::string fname = getFunctionName( appExpr );
-			if ( fname == function->get_name() ) {
+			if ( fname == function->name ) {
 				// call to same kind of function
-				Expression * firstParam = appExpr->get_args().front();
+				Expression * firstParam = appExpr->args.front();
 
 				if ( isThisExpression( firstParam, thisParam ) ) {
@@ -1174,6 +1174,6 @@
 					// if first parameter is a member expression on the this parameter,
 					// then remove the member from unhandled set.
-					if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) {
-						unhandled.erase( memberExpr->get_member() );
+					if ( isThisExpression( memberExpr->aggregate, thisParam ) ) {
+						unhandled.erase( memberExpr->member );
 					}
 				}
Index: src/Parser/DeclarationNode.cc
===================================================================
--- src/Parser/DeclarationNode.cc	(revision bbe1a87944804b0f3c9e486087ca6af21340e747)
+++ src/Parser/DeclarationNode.cc	(revision e3b24743580e0faaf833a980c334820f77cfefaf)
@@ -253,4 +253,22 @@
 	return newnode;
 } // DeclarationNode::newFromTypedef
+
+DeclarationNode * DeclarationNode::newFromGlobalScope() {
+	DeclarationNode * newnode = new DeclarationNode;
+	newnode->type = new TypeData( TypeData::GlobalScope );
+	return newnode;
+}
+
+DeclarationNode * DeclarationNode::newQualifiedType( DeclarationNode * parent, DeclarationNode * child) {
+	DeclarationNode * newnode = new DeclarationNode;
+	newnode->type = new TypeData( TypeData::Qualified );
+	newnode->type->qualified.parent = parent->type;
+	newnode->type->qualified.child = child->type;
+	parent->type = nullptr;
+	child->type = nullptr;
+	delete parent;
+	delete child;
+	return newnode;
+}
 
 DeclarationNode * DeclarationNode::newAggregate( Aggregate kind, const string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body ) {
@@ -993,20 +1011,20 @@
 		try {
 			Declaration * decl = cur->build();
-			if ( decl ) {
-				if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) {
-					dwt->location = cur->location;
-					* out++ = dwt;
-				} else if ( StructDecl * agg = dynamic_cast< StructDecl * >( decl ) ) {
-					StructInstType * inst = new StructInstType( Type::Qualifiers(), agg->get_name() );
-					auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
-					obj->location = cur->location;
-					* out++ = obj;
-					delete agg;
-				} else if ( UnionDecl * agg = dynamic_cast< UnionDecl * >( decl ) ) {
-					UnionInstType * inst = new UnionInstType( Type::Qualifiers(), agg->get_name() );
-					auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
-					obj->location = cur->location;
-					* out++ = obj;
-				} // if
+			assert( decl );
+			if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) {
+				dwt->location = cur->location;
+				* out++ = dwt;
+			} else if ( StructDecl * agg = dynamic_cast< StructDecl * >( decl ) ) {
+				// xxx - this might be where anonymous struct members are added - should be conditional on struct name
+				StructInstType * inst = new StructInstType( Type::Qualifiers(), agg->name );
+				auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
+				obj->location = cur->location;
+				* out++ = obj;
+				delete agg;
+			} else if ( UnionDecl * agg = dynamic_cast< UnionDecl * >( decl ) ) {
+				UnionInstType * inst = new UnionInstType( Type::Qualifiers(), agg->name );
+				auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
+				obj->location = cur->location;
+				* out++ = obj;
 			} // if
 		} catch( SemanticErrorException &e ) {
Index: src/Parser/ParseNode.h
===================================================================
--- src/Parser/ParseNode.h	(revision bbe1a87944804b0f3c9e486087ca6af21340e747)
+++ src/Parser/ParseNode.h	(revision e3b24743580e0faaf833a980c334820f77cfefaf)
@@ -231,4 +231,6 @@
 	static DeclarationNode * newForall( DeclarationNode * );
 	static DeclarationNode * newFromTypedef( const std::string * );
+	static DeclarationNode * newFromGlobalScope();
+	static DeclarationNode * newQualifiedType( DeclarationNode *, DeclarationNode * );
 	static DeclarationNode * newFunction( const std::string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body );
 	static DeclarationNode * newAggregate( Aggregate kind, const std::string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body );
Index: src/Parser/TypeData.cc
===================================================================
--- src/Parser/TypeData.cc	(revision bbe1a87944804b0f3c9e486087ca6af21340e747)
+++ src/Parser/TypeData.cc	(revision e3b24743580e0faaf833a980c334820f77cfefaf)
@@ -37,4 +37,5 @@
 	  case Reference:
 	  case EnumConstant:
+	  case GlobalScope:
 		// nothing else to initialize
 		break;
@@ -98,4 +99,7 @@
 	  case Builtin:
 		// builtin = new Builtin_t;
+		case Qualified:
+		qualified.parent = nullptr;
+		qualified.child = nullptr;
 		break;
 	} // switch
@@ -112,4 +116,5 @@
 	  case Reference:
 	  case EnumConstant:
+	  case GlobalScope:
 		// nothing to destroy
 		break;
@@ -165,4 +170,7 @@
 		// delete builtin;
 		break;
+	  case Qualified:
+		delete qualified.parent;
+		delete qualified.child;
 	} // switch
 } // TypeData::~TypeData
@@ -180,4 +188,5 @@
 	  case Pointer:
 	  case Reference:
+	  case GlobalScope:
 		// nothing else to copy
 		break;
@@ -237,4 +246,8 @@
 		assert( builtintype == DeclarationNode::Zero || builtintype == DeclarationNode::One );
 		newtype->builtintype = builtintype;
+		break;
+		case Qualified:
+		newtype->qualified.parent = maybeClone( qualified.parent );
+		newtype->qualified.child = maybeClone( qualified.child );
 		break;
 	} // switch
@@ -465,5 +478,5 @@
 		return new EnumInstType( buildQualifiers( td ), "" );
 	  case TypeData::SymbolicInst:
-		return buildSymbolicInst( td );;
+		return buildSymbolicInst( td );
 	  case TypeData::Tuple:
 		return buildTuple( td );
@@ -480,4 +493,8 @@
 			return new VarArgsType( buildQualifiers( td ) );
 		}
+	  case TypeData::GlobalScope:
+		return new GlobalScopeType();
+		case TypeData::Qualified:
+		return new QualifiedType( buildQualifiers( td ), typebuild( td->qualified.parent ), typebuild( td->qualified.child ) );
 	  case TypeData::Symbolic:
 	  case TypeData::Enum:
@@ -485,4 +502,5 @@
 		assert( false );
 	} // switch
+
 	return nullptr;
 } // typebuild
@@ -893,10 +911,10 @@
 	assert( td->kind == TypeData::Function );
 	FunctionType * ft = new FunctionType( buildQualifiers( td ), ! td->function.params || td->function.params->hasEllipsis );
-	buildList( td->function.params, ft->get_parameters() );
-	buildForall( td->forall, ft->get_forall() );
+	buildList( td->function.params, ft->parameters );
+	buildForall( td->forall, ft->forall );
 	if ( td->base ) {
 		switch ( td->base->kind ) {
 		  case TypeData::Tuple:
-			buildList( td->base->tuple, ft->get_returnVals() );
+			buildList( td->base->tuple, ft->returnVals );
 			break;
 		  default:
Index: src/Parser/TypeData.h
===================================================================
--- src/Parser/TypeData.h	(revision bbe1a87944804b0f3c9e486087ca6af21340e747)
+++ src/Parser/TypeData.h	(revision e3b24743580e0faaf833a980c334820f77cfefaf)
@@ -27,5 +27,5 @@
 struct TypeData {
 	enum Kind { Basic, Pointer, Array, Reference, Function, Aggregate, AggregateInst, Enum, EnumConstant, Symbolic,
-				SymbolicInst, Tuple, Typeof, Builtin, Unknown };
+				SymbolicInst, Tuple, Typeof, Builtin, GlobalScope, Qualified, Unknown };
 
 	struct Aggregate_t {
@@ -75,4 +75,9 @@
 	};
 
+	struct Qualified_t { // qualified type S.T
+		TypeData * parent;
+		TypeData * child;
+	};
+
 	CodeLocation location;
 
@@ -88,12 +93,11 @@
 	DeclarationNode * forall;
 
-	// Basic_t basic;
 	Aggregate_t aggregate;
 	AggInst_t aggInst;
 	Array_t array;
 	Enumeration_t enumeration;
-	// Variable_t variable;
 	Function_t function;
 	Symbolic_t symbolic;
+	Qualified_t qualified;
 	DeclarationNode * tuple;
 	ExpressionNode * typeexpr;
Index: src/Parser/parser.yy
===================================================================
--- src/Parser/parser.yy	(revision bbe1a87944804b0f3c9e486087ca6af21340e747)
+++ src/Parser/parser.yy	(revision e3b24743580e0faaf833a980c334820f77cfefaf)
@@ -1796,12 +1796,12 @@
 		{ $$ = DeclarationNode::newFromTypedef( $1 ); }
 	| '.' TYPEDEFname
-		{ SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
+		{ $$ = DeclarationNode::newQualifiedType( DeclarationNode::newFromGlobalScope(), DeclarationNode::newFromTypedef( $2 ) ); }
 	| type_name '.' TYPEDEFname
-		{ SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
+		{ $$ = DeclarationNode::newQualifiedType( $1, DeclarationNode::newFromTypedef( $3 ) ); }
 	| typegen_name
 	| '.' typegen_name
-		{ SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
+		{ $$ = DeclarationNode::newQualifiedType( DeclarationNode::newFromGlobalScope(), $2 ); }
 	| type_name '.' typegen_name
-		{ SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
+		{ $$ = DeclarationNode::newQualifiedType( $1, $3 ); }
 	;
 
@@ -1899,10 +1899,8 @@
 		{ distExt( $3 ); $$ = distAttr( $2, $3 ); }		// mark all fields in list
 	| typedef_declaration ';'							// CFA
-		{ SemanticError( yylloc, "Typedef in aggregate is currently unimplemented." ); $$ = nullptr; }
 	| cfa_field_declaring_list ';'						// CFA, new style field declaration
 	| EXTENSION cfa_field_declaring_list ';'			// GCC
 		{ distExt( $2 ); $$ = $2; }						// mark all fields in list
 	| cfa_typedef_declaration ';'						// CFA
-		{ SemanticError( yylloc, "Typedef in aggregate is currently unimplemented." ); $$ = nullptr; }
 	| static_assert										// C11
 	;
Index: src/SymTab/Indexer.cc
===================================================================
--- src/SymTab/Indexer.cc	(revision bbe1a87944804b0f3c9e486087ca6af21340e747)
+++ src/SymTab/Indexer.cc	(revision e3b24743580e0faaf833a980c334820f77cfefaf)
@@ -272,4 +272,20 @@
 	}
 
+	NamedTypeDecl *Indexer::globalLookupType( const std::string &id ) const {
+		return lookupTypeAtScope( id, 0 );
+	}
+
+	StructDecl *Indexer::globalLookupStruct( const std::string &id ) const {
+		return lookupStructAtScope( id, 0 );
+	}
+
+	UnionDecl *Indexer::globalLookupUnion( const std::string &id ) const {
+		return lookupUnionAtScope( id, 0 );
+	}
+
+	EnumDecl *Indexer::globalLookupEnum( const std::string &id ) const {
+		return lookupEnumAtScope( id, 0 );
+	}
+
 	EnumDecl *Indexer::lookupEnum( const std::string &id ) const {
 		if ( ! tables ) return 0;
@@ -347,4 +363,5 @@
 		if ( ! tables ) return 0;
 		if ( tables->scope < scope ) return 0;
+		if ( tables->scope > scope ) return tables->base.lookupTypeAtScope( id, scope );
 
 		TypeTable::const_iterator ret = tables->typeTable.find( id );
@@ -355,4 +372,5 @@
 		if ( ! tables ) return 0;
 		if ( tables->scope < scope ) return 0;
+		if ( tables->scope > scope ) return tables->base.lookupStructAtScope( id, scope );
 
 		StructTable::const_iterator ret = tables->structTable.find( id );
@@ -363,4 +381,5 @@
 		if ( ! tables ) return 0;
 		if ( tables->scope < scope ) return 0;
+		if ( tables->scope > scope ) return tables->base.lookupEnumAtScope( id, scope );
 
 		EnumTable::const_iterator ret = tables->enumTable.find( id );
@@ -371,4 +390,5 @@
 		if ( ! tables ) return 0;
 		if ( tables->scope < scope ) return 0;
+		if ( tables->scope > scope ) return tables->base.lookupUnionAtScope( id, scope );
 
 		UnionTable::const_iterator ret = tables->unionTable.find( id );
@@ -379,4 +399,5 @@
 		if ( ! tables ) return 0;
 		if ( tables->scope < scope ) return 0;
+		if ( tables->scope > scope ) return tables->base.lookupTraitAtScope( id, scope );
 
 		TraitTable::const_iterator ret = tables->traitTable.find( id );
@@ -486,11 +507,17 @@
 
 	bool addedTypeConflicts( NamedTypeDecl *existing, NamedTypeDecl *added ) {
-		if ( existing->get_base() == 0 ) {
+		if ( existing->base == nullptr ) {
 			return false;
-		} else if ( added->get_base() == 0 ) {
+		} else if ( added->base == nullptr ) {
 			return true;
 		} else {
-			SemanticError( added, "redeclaration of " );
-		}
+			assert( existing->base && added->base );
+			// typedef redeclarations are errors only if types are different
+			if ( ! ResolvExpr::typesCompatible( existing->base, added->base, Indexer() ) ) {
+				SemanticError( added->location, "redeclaration of " + added->name );
+			}
+		}
+		// does not need to be added to the table if both existing and added have a base that are the same
+		return true;
 	}
 
@@ -499,5 +526,5 @@
 		makeWritable();
 
-		const std::string &id = decl->get_name();
+		const std::string &id = decl->name;
 		TypeTable::iterator existing = tables->typeTable.find( id );
 		if ( existing == tables->typeTable.end() ) {
@@ -532,5 +559,5 @@
 		makeWritable();
 
-		const std::string &id = decl->get_name();
+		const std::string &id = decl->name;
 		StructTable::iterator existing = tables->structTable.find( id );
 		if ( existing == tables->structTable.end() ) {
@@ -551,5 +578,5 @@
 		makeWritable();
 
-		const std::string &id = decl->get_name();
+		const std::string &id = decl->name;
 		EnumTable::iterator existing = tables->enumTable.find( id );
 		if ( existing == tables->enumTable.end() ) {
@@ -575,5 +602,5 @@
 		makeWritable();
 
-		const std::string &id = decl->get_name();
+		const std::string &id = decl->name;
 		UnionTable::iterator existing = tables->unionTable.find( id );
 		if ( existing == tables->unionTable.end() ) {
@@ -594,5 +621,5 @@
 		makeWritable();
 
-		const std::string &id = decl->get_name();
+		const std::string &id = decl->name;
 		TraitTable::iterator existing = tables->traitTable.find( id );
 		if ( existing == tables->traitTable.end() ) {
Index: src/SymTab/Indexer.h
===================================================================
--- src/SymTab/Indexer.h	(revision bbe1a87944804b0f3c9e486087ca6af21340e747)
+++ src/SymTab/Indexer.h	(revision e3b24743580e0faaf833a980c334820f77cfefaf)
@@ -70,4 +70,13 @@
 		/// Gets the top-most trait declaration with the given ID
 		TraitDecl *lookupTrait( const std::string &id ) const;
+
+		/// Gets the type declaration with the given ID at global scope
+		NamedTypeDecl *globalLookupType( const std::string &id ) const;
+		/// Gets the struct declaration with the given ID at global scope
+		StructDecl *globalLookupStruct( const std::string &id ) const;
+		/// Gets the union declaration with the given ID at global scope
+		UnionDecl *globalLookupUnion( const std::string &id ) const;
+		/// Gets the enum declaration with the given ID at global scope
+		EnumDecl *globalLookupEnum( const std::string &id ) const;
 
 		void print( std::ostream &os, int indent = 0 ) const;
Index: src/SymTab/Mangler.cc
===================================================================
--- src/SymTab/Mangler.cc	(revision bbe1a87944804b0f3c9e486087ca6af21340e747)
+++ src/SymTab/Mangler.cc	(revision e3b24743580e0faaf833a980c334820f77cfefaf)
@@ -60,4 +60,5 @@
 				void postvisit( ZeroType * zeroType );
 				void postvisit( OneType * oneType );
+				void postvisit( QualifiedType * qualType );
 
 				std::string get_mangleName() { return mangleName.str(); }
@@ -171,6 +172,6 @@
 					"w",	// SignedInt128
 					"Uw",	// UnsignedInt128
-					"x",   // Float80
-					"y",   // Float128
+					"x",	// Float80
+					"y",	// Float128
 				};
 				static_assert(
@@ -312,4 +313,10 @@
 			void Mangler::postvisit( OneType * ) {
 				mangleName << "O";
+			}
+
+			void Mangler::postvisit( QualifiedType * qualType ) {
+				maybeAccept( qualType->parent, *visitor );
+				mangleName << "__";
+				maybeAccept( qualType->child, *visitor );
 			}
 
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision bbe1a87944804b0f3c9e486087ca6af21340e747)
+++ src/SymTab/Validate.cc	(revision e3b24743580e0faaf833a980c334820f77cfefaf)
@@ -77,17 +77,29 @@
 class SwitchStmt;
 
-#define debugPrint( x ) if ( doDebug ) { std::cout << x; }
+#define debugPrint( x ) if ( doDebug ) x
 
 namespace SymTab {
+	/// hoists declarations that are difficult to hoist while parsing
+	struct HoistTypeDecls final : public WithDeclsToAdd {
+		void previsit( SizeofExpr * );
+		void previsit( AlignofExpr * );
+		void previsit( UntypedOffsetofExpr * );
+		void handleType( Type * );
+	};
+
+	struct FixQualifiedTypes final : public WithIndexer {
+		Type * postmutate( QualifiedType * );
+	};
+
 	struct HoistStruct final : public WithDeclsToAdd, public WithGuards {
 		/// Flattens nested struct types
 		static void hoistStruct( std::list< Declaration * > &translationUnit );
 
-		void previsit( EnumInstType * enumInstType );
-		void previsit( StructInstType * structInstType );
-		void previsit( UnionInstType * unionInstType );
 		void previsit( StructDecl * aggregateDecl );
 		void previsit( UnionDecl * aggregateDecl );
 		void previsit( StaticAssertDecl * assertDecl );
+		void previsit( StructInstType * type );
+		void previsit( UnionInstType * type );
+		void previsit( EnumInstType * type );
 
 	  private:
@@ -112,5 +124,5 @@
 
 	/// Associates forward declarations of aggregates with their definitions
-	struct LinkReferenceToTypes final : public WithIndexer, public WithGuards {
+	struct LinkReferenceToTypes final : public WithIndexer, public WithGuards, public WithVisitorRef<LinkReferenceToTypes>, public WithShortCircuiting {
 		LinkReferenceToTypes( const Indexer *indexer );
 		void postvisit( TypeInstType *typeInst );
@@ -120,4 +132,6 @@
 		void postvisit( UnionInstType *unionInst );
 		void postvisit( TraitInstType *traitInst );
+		void previsit( QualifiedType * qualType );
+		void postvisit( QualifiedType * qualType );
 
 		void postvisit( EnumDecl *enumDecl );
@@ -165,9 +179,11 @@
 	};
 
-	struct EliminateTypedef final : public WithVisitorRef<EliminateTypedef>, public WithGuards {
-		EliminateTypedef() : scopeLevel( 0 ) {}
+	struct ReplaceTypedef final : public WithVisitorRef<ReplaceTypedef>, public WithGuards, public WithShortCircuiting, public WithDeclsToAdd {
+		ReplaceTypedef() : scopeLevel( 0 ) {}
 		/// Replaces typedefs by forward declarations
-		static void eliminateTypedef( std::list< Declaration * > &translationUnit );
-
+		static void replaceTypedef( std::list< Declaration * > &translationUnit );
+
+		void premutate( QualifiedType * );
+		Type * postmutate( QualifiedType * qualType );
 		Type * postmutate( TypeInstType * aggregateUseType );
 		Declaration * postmutate( TypedefDecl * typeDecl );
@@ -180,13 +196,8 @@
 
 		void premutate( CompoundStmt * compoundStmt );
-		CompoundStmt * postmutate( CompoundStmt * compoundStmt );
 
 		void premutate( StructDecl * structDecl );
-		Declaration * postmutate( StructDecl * structDecl );
 		void premutate( UnionDecl * unionDecl );
-		Declaration * postmutate( UnionDecl * unionDecl );
 		void premutate( EnumDecl * enumDecl );
-		Declaration * postmutate( EnumDecl * enumDecl );
-		Declaration * postmutate( TraitDecl * contextDecl );
 
 		void premutate( FunctionType * ftype );
@@ -194,16 +205,27 @@
 	  private:
 		template<typename AggDecl>
-		AggDecl *handleAggregate( AggDecl * aggDecl );
-
-		template<typename AggDecl>
 		void addImplicitTypedef( AggDecl * aggDecl );
+		template< typename AggDecl >
+		void handleAggregate( AggDecl * aggr );
 
 		typedef std::unique_ptr<TypedefDecl> TypedefDeclPtr;
 		typedef ScopedMap< std::string, std::pair< TypedefDeclPtr, int > > TypedefMap;
-		typedef std::map< std::string, TypeDecl * > TypeDeclMap;
+		typedef std::map< std::string, TypeDecl * > TypeDeclMap; // xxx - convert to ScopedMap
 		TypedefMap typedefNames;
 		TypeDeclMap typedeclNames;
 		int scopeLevel;
 		bool inFunctionType = false;
+	};
+
+	struct EliminateTypedef {
+		/// removes TypedefDecls from the AST
+		static void eliminateTypedef( std::list< Declaration * > &translationUnit );
+
+		template<typename AggDecl>
+		void handleAggregate( AggDecl *aggregateDecl );
+
+		void previsit( StructDecl * aggregateDecl );
+		void previsit( UnionDecl * aggregateDecl );
+		void previsit( CompoundStmt * compoundStmt );
 	};
 
@@ -263,10 +285,15 @@
 		PassVisitor<FindSpecialDeclarations> finder;
 		PassVisitor<LabelAddressFixer> labelAddrFixer;
-
-		EliminateTypedef::eliminateTypedef( translationUnit );
-		HoistStruct::hoistStruct( translationUnit ); // must happen after EliminateTypedef, so that aggregate typedefs occur in the correct order
+		PassVisitor<HoistTypeDecls> hoistDecls;
+		PassVisitor<FixQualifiedTypes> fixQual;
+
+		acceptAll( translationUnit, hoistDecls );
+		ReplaceTypedef::replaceTypedef( translationUnit );
 		ReturnTypeFixer::fix( translationUnit ); // must happen before autogen
 		acceptAll( translationUnit, epc ); // must happen before VerifyCtorDtorAssign, because void return objects should not exist; before LinkReferenceToTypes because it is an indexer and needs correct types for mangling
 		acceptAll( translationUnit, lrt ); // must happen before autogen, because sized flag needs to propagate to generated functions
+		mutateAll( translationUnit, fixQual ); // must happen after LinkReferenceToTypes, because aggregate members are accessed
+		HoistStruct::hoistStruct( translationUnit ); // must happen after EliminateTypedef, so that aggregate typedefs occur in the correct order
+		EliminateTypedef::eliminateTypedef( translationUnit ); //
 		acceptAll( translationUnit, genericParams );  // check as early as possible - can't happen before LinkReferenceToTypes
 		VerifyCtorDtorAssign::verify( translationUnit );  // must happen before autogen, because autogen examines existing ctor/dtors
@@ -294,4 +321,109 @@
 	}
 
+
+	void HoistTypeDecls::handleType( Type * type ) {
+		// some type declarations are buried in expressions and not easy to hoist during parsing; hoist them here
+		AggregateDecl * aggr = nullptr;
+		if ( StructInstType * inst = dynamic_cast< StructInstType * >( type ) ) {
+			aggr = inst->baseStruct;
+		} else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( type ) ) {
+			aggr = inst->baseUnion;
+		} else if ( EnumInstType * inst = dynamic_cast< EnumInstType * >( type ) ) {
+			aggr = inst->baseEnum;
+		}
+		if ( aggr && aggr->body ) {
+			declsToAddBefore.push_front( aggr );
+		}
+	}
+
+	void HoistTypeDecls::previsit( SizeofExpr * expr ) {
+		handleType( expr->type );
+	}
+
+	void HoistTypeDecls::previsit( AlignofExpr * expr ) {
+		handleType( expr->type );
+	}
+
+	void HoistTypeDecls::previsit( UntypedOffsetofExpr * expr ) {
+		handleType( expr->type );
+	}
+
+
+	Type * FixQualifiedTypes::postmutate( QualifiedType * qualType ) {
+		// TODO: change asserts to SemanticErrors as necessary
+		Type * parent = qualType->parent;
+		Type * child = qualType->child;
+		if ( dynamic_cast< GlobalScopeType * >( qualType->parent ) ) {
+			// .T => lookup T at global scope
+			if ( StructInstType * inst = dynamic_cast< StructInstType * >( child ) ) {
+				auto aggr = indexer.globalLookupStruct( inst->name );
+				return new StructInstType( qualType->get_qualifiers(), aggr );
+			} else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( child ) ) {
+				auto aggr =  indexer.globalLookupUnion( inst->name );
+				return new UnionInstType( qualType->get_qualifiers(), aggr );
+			} else if ( EnumInstType * inst = dynamic_cast< EnumInstType * >( child ) ) {
+				auto aggr = indexer.globalLookupEnum( inst->name );
+				return new EnumInstType( qualType->get_qualifiers(), aggr );
+			} else if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( child ) ) {
+				auto td = indexer.globalLookupType( inst->name );
+				assertf( td, "did not find type at global scope with name: %s", inst->name.c_str() );
+				auto base = td->base;
+				if ( base ) return td->base->clone();
+				assert( false );
+			} else {
+				// .T => T is not a SUE type name
+				assert( false );
+			}
+		} else {
+			// S.T => S must be an aggregate type, find the declaration for T in S.
+			AggregateDecl * aggr = nullptr;
+			if ( StructInstType * inst = dynamic_cast< StructInstType * >( parent ) ) {
+				aggr = inst->baseStruct;
+			} else if ( UnionInstType * inst = dynamic_cast< UnionInstType * > ( parent ) ) {
+				aggr = inst->baseUnion;
+			} else {
+				assert( false );
+			}
+			assert( aggr ); // TODO: need to handle forward declarations
+			for ( Declaration * member : aggr->members ) {
+				if ( StructInstType * inst = dynamic_cast< StructInstType * >( child ) ) {
+					if ( StructDecl * aggr = dynamic_cast< StructDecl * >( member ) ) {
+						if ( aggr->name == inst->name ) {
+							return new StructInstType( qualType->get_qualifiers(), aggr );
+						}
+					}
+				} else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( child ) ) {
+					if ( UnionDecl * aggr = dynamic_cast< UnionDecl * > ( member ) ) {
+						if ( aggr->name == inst->name ) {
+							return new UnionInstType( qualType->get_qualifiers(), aggr );
+						}
+					}
+				} else if ( EnumInstType * inst = dynamic_cast< EnumInstType * >( child ) ) {
+					if ( EnumDecl * aggr = dynamic_cast< EnumDecl * > ( member ) ) {
+						if ( aggr->name == inst->name ) {
+							return new EnumInstType( qualType->get_qualifiers(), aggr );
+						}
+					}
+				} else if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( child ) ) {
+					// struct typedefs are being replaced by forward decls too early; move it to hoist struct
+					if ( NamedTypeDecl * aggr = dynamic_cast< NamedTypeDecl * > ( member ) ) {
+						if ( aggr->name == inst->name ) {
+							if ( aggr->base ) return aggr->base->clone();
+							assert( false );
+						}
+					}
+				} else {
+					// S.T - S is not an aggregate => error
+					assertf( false, "unhandled qualified child type: %s", toCString(qualType) );
+				}
+			}
+			// failed to find a satisfying definition of type
+			assertf( false, "failed to find a satisfying definition of %s in %s", toCString(child), toCString(parent) );
+		}
+
+		// ... may want to link canonical SUE definition to each forward decl so that it becomes easier to lookup?
+	}
+
+
 	void HoistStruct::hoistStruct( std::list< Declaration * > &translationUnit ) {
 		PassVisitor<HoistStruct> hoister;
@@ -303,7 +435,23 @@
 	}
 
+	namespace {
+		void qualifiedName( AggregateDecl * aggr, std::ostringstream & ss ) {
+			if ( aggr->parent ) qualifiedName( aggr->parent, ss );
+			ss << "__" << aggr->name;
+		}
+
+		// mangle nested type names using entire parent chain
+		std::string qualifiedName( AggregateDecl * aggr ) {
+			std::ostringstream ss;
+			qualifiedName( aggr, ss );
+			return ss.str();
+		}
+	}
+
 	template< typename AggDecl >
 	void HoistStruct::handleAggregate( AggDecl *aggregateDecl ) {
 		if ( parentAggr ) {
+			aggregateDecl->parent = parentAggr;
+			aggregateDecl->name = qualifiedName( aggregateDecl );
 			// Add elements in stack order corresponding to nesting structure.
 			declsToAddBefore.push_front( aggregateDecl );
@@ -316,22 +464,4 @@
 	}
 
-	void HoistStruct::previsit( EnumInstType * inst ) {
-		if ( inst->baseEnum && inst->baseEnum->body ) {
-			declsToAddBefore.push_front( inst->baseEnum );
-		}
-	}
-
-	void HoistStruct::previsit( StructInstType * inst ) {
-		if ( inst->baseStruct && inst->baseStruct->body ) {
-			declsToAddBefore.push_front( inst->baseStruct );
-		}
-	}
-
-	void HoistStruct::previsit( UnionInstType * inst ) {
-		if ( inst->baseUnion && inst->baseUnion->body ) {
-			declsToAddBefore.push_front( inst->baseUnion );
-		}
-	}
-
 	void HoistStruct::previsit( StaticAssertDecl * assertDecl ) {
 		if ( parentAggr ) {
@@ -348,10 +478,62 @@
 	}
 
+	void HoistStruct::previsit( StructInstType * type ) {
+		// need to reset type name after expanding to qualified name
+		assert( type->baseStruct );
+		type->name = type->baseStruct->name;
+	}
+
+	void HoistStruct::previsit( UnionInstType * type ) {
+		assert( type->baseUnion );
+		type->name = type->baseUnion->name;
+	}
+
+	void HoistStruct::previsit( EnumInstType * type ) {
+		assert( type->baseEnum );
+		type->name = type->baseEnum->name;
+	}
+
+
+	bool isTypedef( Declaration *decl ) {
+		return dynamic_cast< TypedefDecl * >( decl );
+	}
+
+	void EliminateTypedef::eliminateTypedef( std::list< Declaration * > &translationUnit ) {
+		PassVisitor<EliminateTypedef> eliminator;
+		acceptAll( translationUnit, eliminator );
+		filter( translationUnit, isTypedef, true );
+	}
+
+	template< typename AggDecl >
+	void EliminateTypedef::handleAggregate( AggDecl *aggregateDecl ) {
+		filter( aggregateDecl->members, isTypedef, true );
+	}
+
+	void EliminateTypedef::previsit( StructDecl * aggregateDecl ) {
+		handleAggregate( aggregateDecl );
+	}
+
+	void EliminateTypedef::previsit( UnionDecl * aggregateDecl ) {
+		handleAggregate( aggregateDecl );
+	}
+
+	void EliminateTypedef::previsit( CompoundStmt * compoundStmt ) {
+		// remove and delete decl stmts
+		filter( compoundStmt->kids, [](Statement * stmt) {
+			if ( DeclStmt *declStmt = dynamic_cast< DeclStmt * >( stmt ) ) {
+				if ( dynamic_cast< TypedefDecl * >( declStmt->decl ) ) {
+					return true;
+				} // if
+			} // if
+			return false;
+		}, true);
+	}
+
 	void EnumAndPointerDecay::previsit( EnumDecl *enumDecl ) {
 		// Set the type of each member of the enumeration to be EnumConstant
-		for ( std::list< Declaration * >::iterator i = enumDecl->get_members().begin(); i != enumDecl->get_members().end(); ++i ) {
+		for ( std::list< Declaration * >::iterator i = enumDecl->members.begin(); i != enumDecl->members.end(); ++i ) {
 			ObjectDecl * obj = dynamic_cast< ObjectDecl * >( *i );
 			assert( obj );
-			obj->set_type( new EnumInstType( Type::Qualifiers( Type::Const ), enumDecl->get_name() ) );
+			obj->set_type( new EnumInstType( Type::Qualifiers( Type::Const ), enumDecl->name ) );
 		} // for
 	}
@@ -395,13 +577,12 @@
 
 	void LinkReferenceToTypes::postvisit( EnumInstType *enumInst ) {
-		EnumDecl *st = local_indexer->lookupEnum( enumInst->get_name() );
+		EnumDecl *st = local_indexer->lookupEnum( enumInst->name );
 		// it's not a semantic error if the enum is not found, just an implicit forward declaration
 		if ( st ) {
-			//assert( ! enumInst->get_baseEnum() || enumInst->get_baseEnum()->get_members().empty() || ! st->get_members().empty() );
-			enumInst->set_baseEnum( st );
-		} // if
-		if ( ! st || st->get_members().empty() ) {
+			enumInst->baseEnum = st;
+		} // if
+		if ( ! st || ! st->body ) {
 			// use of forward declaration
-			forwardEnums[ enumInst->get_name() ].push_back( enumInst );
+			forwardEnums[ enumInst->name ].push_back( enumInst );
 		} // if
 	}
@@ -416,13 +597,12 @@
 
 	void LinkReferenceToTypes::postvisit( StructInstType *structInst ) {
-		StructDecl *st = local_indexer->lookupStruct( structInst->get_name() );
+		StructDecl *st = local_indexer->lookupStruct( structInst->name );
 		// it's not a semantic error if the struct is not found, just an implicit forward declaration
 		if ( st ) {
-			//assert( ! structInst->get_baseStruct() || structInst->get_baseStruct()->get_members().empty() || ! st->get_members().empty() );
-			structInst->set_baseStruct( st );
-		} // if
-		if ( ! st || st->get_members().empty() ) {
+			structInst->baseStruct = st;
+		} // if
+		if ( ! st || ! st->body ) {
 			// use of forward declaration
-			forwardStructs[ structInst->get_name() ].push_back( structInst );
+			forwardStructs[ structInst->name ].push_back( structInst );
 		} // if
 		checkGenericParameters( structInst );
@@ -430,14 +610,23 @@
 
 	void LinkReferenceToTypes::postvisit( UnionInstType *unionInst ) {
-		UnionDecl *un = local_indexer->lookupUnion( unionInst->get_name() );
+		UnionDecl *un = local_indexer->lookupUnion( unionInst->name );
 		// it's not a semantic error if the union is not found, just an implicit forward declaration
 		if ( un ) {
-			unionInst->set_baseUnion( un );
-		} // if
-		if ( ! un || un->get_members().empty() ) {
+			unionInst->baseUnion = un;
+		} // if
+		if ( ! un || ! un->body ) {
 			// use of forward declaration
-			forwardUnions[ unionInst->get_name() ].push_back( unionInst );
+			forwardUnions[ unionInst->name ].push_back( unionInst );
 		} // if
 		checkGenericParameters( unionInst );
+	}
+
+	void LinkReferenceToTypes::previsit( QualifiedType * ) {
+		visit_children = false;
+	}
+
+	void LinkReferenceToTypes::postvisit( QualifiedType * qualType ) {
+		// linking only makes sense for the 'oldest ancestor' of the qualified type
+		qualType->parent->accept( *visitor );
 	}
 
@@ -450,5 +639,5 @@
 			DeclarationWithType * dwt2 = dynamic_cast<DeclarationWithType *>( d2 );
 			if ( dwt1 && dwt2 ) {
-				if ( dwt1->get_name() == dwt2->get_name() && ResolvExpr::typesCompatible( dwt1->get_type(), dwt2->get_type(), SymTab::Indexer() ) ) {
+				if ( dwt1->name == dwt2->name && ResolvExpr::typesCompatible( dwt1->get_type(), dwt2->get_type(), SymTab::Indexer() ) ) {
 					// std::cerr << "=========== equal:" << std::endl;
 					// std::cerr << "d1: " << d1 << std::endl;
@@ -475,5 +664,5 @@
 	template< typename Iterator >
 	void expandAssertions( TraitInstType * inst, Iterator out ) {
-		assertf( inst->baseTrait, "Trait instance not linked to base trait: %s", toString( inst ).c_str() );
+		assertf( inst->baseTrait, "Trait instance not linked to base trait: %s", toCString( inst ) );
 		std::list< DeclarationWithType * > asserts;
 		for ( Declaration * decl : inst->baseTrait->members ) {
@@ -512,5 +701,5 @@
 			SemanticError( traitInst->location, "use of undeclared trait " + traitInst->name );
 		} // if
-		if ( traitDecl->get_parameters().size() != traitInst->get_parameters().size() ) {
+		if ( traitDecl->parameters.size() != traitInst->parameters.size() ) {
 			SemanticError( traitInst, "incorrect number of trait parameters: " );
 		} // if
@@ -518,5 +707,5 @@
 
 		// need to carry over the 'sized' status of each decl in the instance
-		for ( auto p : group_iterate( traitDecl->get_parameters(), traitInst->get_parameters() ) ) {
+		for ( auto p : group_iterate( traitDecl->parameters, traitInst->parameters ) ) {
 			TypeExpr * expr = dynamic_cast< TypeExpr * >( std::get<1>(p) );
 			if ( ! expr ) {
@@ -525,5 +714,5 @@
 			if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( expr->get_type() ) ) {
 				TypeDecl * formalDecl = std::get<0>(p);
-				TypeDecl * instDecl = inst->get_baseType();
+				TypeDecl * instDecl = inst->baseType;
 				if ( formalDecl->get_sized() ) instDecl->set_sized( true );
 			}
@@ -534,9 +723,9 @@
 	void LinkReferenceToTypes::postvisit( EnumDecl *enumDecl ) {
 		// visit enum members first so that the types of self-referencing members are updated properly
-		if ( ! enumDecl->get_members().empty() ) {
-			ForwardEnumsType::iterator fwds = forwardEnums.find( enumDecl->get_name() );
+		if ( enumDecl->body ) {
+			ForwardEnumsType::iterator fwds = forwardEnums.find( enumDecl->name );
 			if ( fwds != forwardEnums.end() ) {
 				for ( std::list< EnumInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) {
-					(*inst )->set_baseEnum( enumDecl );
+					(*inst)->baseEnum = enumDecl;
 				} // for
 				forwardEnums.erase( fwds );
@@ -574,9 +763,9 @@
 		// visit struct members first so that the types of self-referencing members are updated properly
 		// xxx - need to ensure that type parameters match up between forward declarations and definition (most importantly, number of type parameters and their defaults)
-		if ( ! structDecl->get_members().empty() ) {
-			ForwardStructsType::iterator fwds = forwardStructs.find( structDecl->get_name() );
+		if ( structDecl->body ) {
+			ForwardStructsType::iterator fwds = forwardStructs.find( structDecl->name );
 			if ( fwds != forwardStructs.end() ) {
 				for ( std::list< StructInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) {
-					(*inst )->set_baseStruct( structDecl );
+					(*inst)->baseStruct = structDecl;
 				} // for
 				forwardStructs.erase( fwds );
@@ -586,9 +775,9 @@
 
 	void LinkReferenceToTypes::postvisit( UnionDecl *unionDecl ) {
-		if ( ! unionDecl->get_members().empty() ) {
-			ForwardUnionsType::iterator fwds = forwardUnions.find( unionDecl->get_name() );
+		if ( unionDecl->body ) {
+			ForwardUnionsType::iterator fwds = forwardUnions.find( unionDecl->name );
 			if ( fwds != forwardUnions.end() ) {
 				for ( std::list< UnionInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) {
-					(*inst )->set_baseUnion( unionDecl );
+					(*inst)->baseUnion = unionDecl;
 				} // for
 				forwardUnions.erase( fwds );
@@ -600,5 +789,5 @@
 		// ensure generic parameter instances are renamed like the base type
 		if ( inGeneric && typeInst->baseType ) typeInst->name = typeInst->baseType->name;
-		if ( NamedTypeDecl *namedTypeDecl = local_indexer->lookupType( typeInst->get_name() ) ) {
+		if ( NamedTypeDecl *namedTypeDecl = local_indexer->lookupType( typeInst->name ) ) {
 			if ( TypeDecl *typeDecl = dynamic_cast< TypeDecl * >( namedTypeDecl ) ) {
 				typeInst->set_isFtype( typeDecl->get_kind() == TypeDecl::Ftype );
@@ -679,14 +868,10 @@
 
 
-	bool isTypedef( Declaration *decl ) {
-		return dynamic_cast< TypedefDecl * >( decl );
-	}
-
-	void EliminateTypedef::eliminateTypedef( std::list< Declaration * > &translationUnit ) {
-		PassVisitor<EliminateTypedef> eliminator;
+	void ReplaceTypedef::replaceTypedef( std::list< Declaration * > &translationUnit ) {
+		PassVisitor<ReplaceTypedef> eliminator;
 		mutateAll( translationUnit, eliminator );
 		if ( eliminator.pass.typedefNames.count( "size_t" ) ) {
 			// grab and remember declaration of size_t
-			SizeType = eliminator.pass.typedefNames["size_t"].first->get_base()->clone();
+			SizeType = eliminator.pass.typedefNames["size_t"].first->base->clone();
 		} else {
 			// xxx - missing global typedef for size_t - default to long unsigned int, even though that may be wrong
@@ -694,11 +879,20 @@
 			SizeType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
 		}
-		filter( translationUnit, isTypedef, true );
-	}
-
-	Type * EliminateTypedef::postmutate( TypeInstType * typeInst ) {
+	}
+
+	void ReplaceTypedef::premutate( QualifiedType * ) {
+		visit_children = false;
+	}
+
+	Type * ReplaceTypedef::postmutate( QualifiedType * qualType ) {
+		// replacing typedefs only makes sense for the 'oldest ancestor' of the qualified type
+		qualType->parent = qualType->parent->acceptMutator( *visitor );
+		return qualType;
+	}
+
+	Type * ReplaceTypedef::postmutate( TypeInstType * typeInst ) {
 		// instances of typedef types will come here. If it is an instance
 		// of a typdef type, link the instance to its actual type.
-		TypedefMap::const_iterator def = typedefNames.find( typeInst->get_name() );
+		TypedefMap::const_iterator def = typedefNames.find( typeInst->name );
 		if ( def != typedefNames.end() ) {
 			Type *ret = def->second.first->base->clone();
@@ -717,5 +911,5 @@
 					SemanticError( typeInst->location, "Cannot apply type parameters to base type of " + typeInst->name );
 				}
-				rtt->get_parameters().clear();
+				rtt->parameters.clear();
 				cloneAll( typeInst->parameters, rtt->parameters );
 				mutateAll( rtt->parameters, *visitor );  // recursively fix typedefs on parameters
@@ -724,5 +918,5 @@
 			return ret;
 		} else {
-			TypeDeclMap::const_iterator base = typedeclNames.find( typeInst->get_name() );
+			TypeDeclMap::const_iterator base = typedeclNames.find( typeInst->name );
 			assertf( base != typedeclNames.end(), "Cannot find typedecl name %s", typeInst->name.c_str() );
 			typeInst->set_baseType( base->second );
@@ -745,11 +939,11 @@
 	}
 
-	Declaration *EliminateTypedef::postmutate( TypedefDecl * tyDecl ) {
-		if ( typedefNames.count( tyDecl->get_name() ) == 1 && typedefNames[ tyDecl->get_name() ].second == scopeLevel ) {
+	Declaration * ReplaceTypedef::postmutate( TypedefDecl * tyDecl ) {
+		if ( typedefNames.count( tyDecl->name ) == 1 && typedefNames[ tyDecl->name ].second == scopeLevel ) {
 			// typedef to the same name from the same scope
 			// must be from the same type
 
-			Type * t1 = tyDecl->get_base();
-			Type * t2 = typedefNames[ tyDecl->get_name() ].first->get_base();
+			Type * t1 = tyDecl->base;
+			Type * t2 = typedefNames[ tyDecl->name ].first->base;
 			if ( ! ResolvExpr::typesCompatible( t1, t2, Indexer() ) ) {
 				SemanticError( tyDecl->location, "Cannot redefine typedef: " + tyDecl->name );
@@ -763,5 +957,5 @@
 			}
 		} else {
-			typedefNames[ tyDecl->get_name() ] = std::make_pair( TypedefDeclPtr( tyDecl ), scopeLevel );
+			typedefNames[ tyDecl->name ] = std::make_pair( TypedefDeclPtr( tyDecl ), scopeLevel );
 		} // if
 
@@ -775,38 +969,37 @@
 		// Note, qualifiers on the typedef are superfluous for the forward declaration.
 
-		Type *designatorType = tyDecl->get_base()->stripDeclarator();
+		Type *designatorType = tyDecl->base->stripDeclarator();
 		if ( StructInstType *aggDecl = dynamic_cast< StructInstType * >( designatorType ) ) {
-			return new StructDecl( aggDecl->get_name(), DeclarationNode::Struct, noAttributes, tyDecl->get_linkage() );
+			declsToAddBefore.push_back( new StructDecl( aggDecl->name, DeclarationNode::Struct, noAttributes, tyDecl->linkage ) );
 		} else if ( UnionInstType *aggDecl = dynamic_cast< UnionInstType * >( designatorType ) ) {
-			return new UnionDecl( aggDecl->get_name(), noAttributes, tyDecl->get_linkage() );
+			declsToAddBefore.push_back( new UnionDecl( aggDecl->name, noAttributes, tyDecl->linkage ) );
 		} else if ( EnumInstType *enumDecl = dynamic_cast< EnumInstType * >( designatorType ) ) {
-			return new EnumDecl( enumDecl->get_name(), noAttributes, tyDecl->get_linkage() );
-		} else {
-			return tyDecl->clone();
-		} // if
-	}
-
-	void EliminateTypedef::premutate( TypeDecl * typeDecl ) {
-		TypedefMap::iterator i = typedefNames.find( typeDecl->get_name() );
+			declsToAddBefore.push_back( new EnumDecl( enumDecl->name, noAttributes, tyDecl->linkage ) );
+		} // if
+		return tyDecl->clone();
+	}
+
+	void ReplaceTypedef::premutate( TypeDecl * typeDecl ) {
+		TypedefMap::iterator i = typedefNames.find( typeDecl->name );
 		if ( i != typedefNames.end() ) {
 			typedefNames.erase( i ) ;
 		} // if
 
-		typedeclNames[ typeDecl->get_name() ] = typeDecl;
-	}
-
-	void EliminateTypedef::premutate( FunctionDecl * ) {
+		typedeclNames[ typeDecl->name ] = typeDecl;
+	}
+
+	void ReplaceTypedef::premutate( FunctionDecl * ) {
 		GuardScope( typedefNames );
 	}
 
-	void EliminateTypedef::premutate( ObjectDecl * ) {
+	void ReplaceTypedef::premutate( ObjectDecl * ) {
 		GuardScope( typedefNames );
 	}
 
-	DeclarationWithType *EliminateTypedef::postmutate( ObjectDecl * objDecl ) {
-		if ( FunctionType *funtype = dynamic_cast<FunctionType *>( objDecl->get_type() ) ) { // function type?
+	DeclarationWithType * ReplaceTypedef::postmutate( ObjectDecl * objDecl ) {
+		if ( FunctionType *funtype = dynamic_cast<FunctionType *>( objDecl->type ) ) { // function type?
 			// replace the current object declaration with a function declaration
-			FunctionDecl * newDecl = new FunctionDecl( objDecl->get_name(), objDecl->get_storageClasses(), objDecl->get_linkage(), funtype, 0, objDecl->get_attributes(), objDecl->get_funcSpec() );
-			objDecl->get_attributes().clear();
+			FunctionDecl * newDecl = new FunctionDecl( objDecl->name, objDecl->get_storageClasses(), objDecl->linkage, funtype, 0, objDecl->attributes, objDecl->get_funcSpec() );
+			objDecl->attributes.clear();
 			objDecl->set_type( nullptr );
 			delete objDecl;
@@ -816,9 +1009,9 @@
 	}
 
-	void EliminateTypedef::premutate( CastExpr * ) {
+	void ReplaceTypedef::premutate( CastExpr * ) {
 		GuardScope( typedefNames );
 	}
 
-	void EliminateTypedef::premutate( CompoundStmt * ) {
+	void ReplaceTypedef::premutate( CompoundStmt * ) {
 		GuardScope( typedefNames );
 		scopeLevel += 1;
@@ -826,27 +1019,6 @@
 	}
 
-	CompoundStmt *EliminateTypedef::postmutate( CompoundStmt * compoundStmt ) {
-		// remove and delete decl stmts
-		filter( compoundStmt->kids, [](Statement * stmt) {
-			if ( DeclStmt *declStmt = dynamic_cast< DeclStmt * >( stmt ) ) {
-				if ( dynamic_cast< TypedefDecl * >( declStmt->get_decl() ) ) {
-					return true;
-				} // if
-			} // if
-			return false;
-		}, true);
-		return compoundStmt;
-	}
-
-	// there may be typedefs nested within aggregates. in order for everything to work properly, these should be removed
-	// as well
 	template<typename AggDecl>
-	AggDecl *EliminateTypedef::handleAggregate( AggDecl * aggDecl ) {
-		filter( aggDecl->members, isTypedef, true );
-		return aggDecl;
-	}
-
-	template<typename AggDecl>
-	void EliminateTypedef::addImplicitTypedef( AggDecl * aggDecl ) {
+	void ReplaceTypedef::addImplicitTypedef( AggDecl * aggDecl ) {
 		if ( typedefNames.count( aggDecl->get_name() ) == 0 ) {
 			Type *type = nullptr;
@@ -860,37 +1032,55 @@
 			TypedefDeclPtr tyDecl( new TypedefDecl( aggDecl->get_name(), aggDecl->location, Type::StorageClasses(), type, aggDecl->get_linkage() ) );
 			typedefNames[ aggDecl->get_name() ] = std::make_pair( std::move( tyDecl ), scopeLevel );
-		} // if
-	}
-
-	void EliminateTypedef::premutate( StructDecl * structDecl ) {
+			// add the implicit typedef to the AST
+			declsToAddBefore.push_back( new TypedefDecl( aggDecl->get_name(), aggDecl->location, Type::StorageClasses(), type->clone(), aggDecl->get_linkage() ) );
+		} // if
+	}
+
+	template< typename AggDecl >
+	void ReplaceTypedef::handleAggregate( AggDecl * aggr ) {
+		SemanticErrorException errors;
+
+		ValueGuard< std::list<Declaration * > > oldBeforeDecls( declsToAddBefore );
+		ValueGuard< std::list<Declaration * > > oldAfterDecls ( declsToAddAfter  );
+		declsToAddBefore.clear();
+		declsToAddAfter.clear();
+
+		GuardScope( typedefNames );
+		mutateAll( aggr->parameters, *visitor );
+
+		// unroll mutateAll for aggr->members so that implicit typedefs for nested types are added to the aggregate body.
+		for ( std::list< Declaration * >::iterator i = aggr->members.begin(); i != aggr->members.end(); ++i ) {
+			if ( !declsToAddAfter.empty() ) { aggr->members.splice( i, declsToAddAfter ); }
+
+			try {
+				*i = maybeMutate( *i, *visitor );
+			} catch ( SemanticErrorException &e ) {
+				errors.append( e );
+			}
+
+			if ( !declsToAddBefore.empty() ) { aggr->members.splice( i, declsToAddBefore ); }
+		}
+
+		if ( !declsToAddAfter.empty() ) { aggr->members.splice( aggr->members.end(), declsToAddAfter ); }
+		if ( !errors.isEmpty() ) { throw errors; }
+	}
+
+	void ReplaceTypedef::premutate( StructDecl * structDecl ) {
+		visit_children = false;
 		addImplicitTypedef( structDecl );
-	}
-
-
-	Declaration *EliminateTypedef::postmutate( StructDecl * structDecl ) {
-		return handleAggregate( structDecl );
-	}
-
-	void EliminateTypedef::premutate( UnionDecl * unionDecl ) {
+		handleAggregate( structDecl );
+	}
+
+	void ReplaceTypedef::premutate( UnionDecl * unionDecl ) {
+		visit_children = false;
 		addImplicitTypedef( unionDecl );
-	}
-
-	Declaration *EliminateTypedef::postmutate( UnionDecl * unionDecl ) {
-		return handleAggregate( unionDecl );
-	}
-
-	void EliminateTypedef::premutate( EnumDecl * enumDecl ) {
+		handleAggregate( unionDecl );
+	}
+
+	void ReplaceTypedef::premutate( EnumDecl * enumDecl ) {
 		addImplicitTypedef( enumDecl );
 	}
 
-	Declaration *EliminateTypedef::postmutate( EnumDecl * enumDecl ) {
-		return handleAggregate( enumDecl );
-	}
-
-	Declaration *EliminateTypedef::postmutate( TraitDecl * traitDecl ) {
-		return handleAggregate( traitDecl );
-	}
-
-	void EliminateTypedef::premutate( FunctionType * ) {
+	void ReplaceTypedef::premutate( FunctionType * ) {
 		GuardValue( inFunctionType );
 		inFunctionType = true;
@@ -1024,8 +1214,8 @@
 
 	void ArrayLength::previsit( ObjectDecl * objDecl ) {
-		if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) {
+		if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->type ) ) {
 			if ( at->get_dimension() ) return;
-			if ( ListInit * init = dynamic_cast< ListInit * >( objDecl->get_init() ) ) {
-				at->set_dimension( new ConstantExpr( Constant::from_ulong( init->get_initializers().size() ) ) );
+			if ( ListInit * init = dynamic_cast< ListInit * >( objDecl->init ) ) {
+				at->set_dimension( new ConstantExpr( Constant::from_ulong( init->initializers.size() ) ) );
 			}
 		}
Index: src/SynTree/Declaration.h
===================================================================
--- src/SynTree/Declaration.h	(revision bbe1a87944804b0f3c9e486087ca6af21340e747)
+++ src/SynTree/Declaration.h	(revision e3b24743580e0faaf833a980c334820f77cfefaf)
@@ -266,4 +266,5 @@
 	bool body;
 	std::list< Attribute * > attributes;
+	AggregateDecl * parent = nullptr;
 
 	AggregateDecl( const std::string &name, const std::list< Attribute * > & attributes = std::list< class Attribute * >(), LinkageSpec::Spec linkage = LinkageSpec::Cforall );
Index: src/SynTree/Mutator.h
===================================================================
--- src/SynTree/Mutator.h	(revision bbe1a87944804b0f3c9e486087ca6af21340e747)
+++ src/SynTree/Mutator.h	(revision e3b24743580e0faaf833a980c334820f77cfefaf)
@@ -101,4 +101,5 @@
 	virtual Type * mutate( ArrayType * arrayType ) = 0;
 	virtual Type * mutate( ReferenceType * refType ) = 0;
+	virtual Type * mutate( QualifiedType * qualType ) = 0;
 	virtual Type * mutate( FunctionType * functionType ) = 0;
 	virtual Type * mutate( StructInstType * aggregateUseType ) = 0;
@@ -113,4 +114,5 @@
 	virtual Type * mutate( ZeroType * zeroType ) = 0;
 	virtual Type * mutate( OneType * oneType ) = 0;
+	virtual Type * mutate( GlobalScopeType * globalType ) = 0;
 
 	virtual Designation * mutate( Designation * designation ) = 0 ;
Index: src/SynTree/ReferenceToType.cc
===================================================================
--- src/SynTree/ReferenceToType.cc	(revision bbe1a87944804b0f3c9e486087ca6af21340e747)
+++ src/SynTree/ReferenceToType.cc	(revision e3b24743580e0faaf833a980c334820f77cfefaf)
@@ -76,5 +76,5 @@
 bool StructInstType::isComplete() const { return baseStruct ? baseStruct->has_body() : false; }
 
-AggregateDecl * StructInstType::getAggr() { return baseStruct; }
+AggregateDecl * StructInstType::getAggr() const { return baseStruct; }
 
 TypeSubstitution StructInstType::genericSubstitution() const {
@@ -119,5 +119,5 @@
 bool UnionInstType::isComplete() const { return baseUnion ? baseUnion->has_body() : false; }
 
-AggregateDecl * UnionInstType::getAggr() { return baseUnion; }
+AggregateDecl * UnionInstType::getAggr() const { return baseUnion; }
 
 TypeSubstitution UnionInstType::genericSubstitution() const {
@@ -152,4 +152,6 @@
 bool EnumInstType::isComplete() const { return baseEnum ? baseEnum->has_body() : false; }
 
+AggregateDecl * EnumInstType::getAggr() const { return baseEnum; }
+
 void EnumInstType::print( std::ostream &os, Indenter indent ) const {
 	using std::endl;
Index: src/SynTree/SynTree.h
===================================================================
--- src/SynTree/SynTree.h	(revision bbe1a87944804b0f3c9e486087ca6af21340e747)
+++ src/SynTree/SynTree.h	(revision e3b24743580e0faaf833a980c334820f77cfefaf)
@@ -110,4 +110,5 @@
 class ArrayType;
 class ReferenceType;
+class QualifiedType;
 class FunctionType;
 class ReferenceToType;
@@ -123,4 +124,5 @@
 class ZeroType;
 class OneType;
+class GlobalScopeType;
 
 class Designation;
Index: src/SynTree/Type.cc
===================================================================
--- src/SynTree/Type.cc	(revision bbe1a87944804b0f3c9e486087ca6af21340e747)
+++ src/SynTree/Type.cc	(revision e3b24743580e0faaf833a980c334820f77cfefaf)
@@ -105,4 +105,33 @@
 }
 
+
+QualifiedType::QualifiedType( const Type::Qualifiers & tq, Type * parent, Type * child ) : Type( tq, {} ), parent( parent ), child( child ) {
+}
+
+QualifiedType::QualifiedType( const QualifiedType & other ) : Type( other ), parent( maybeClone( other.parent ) ), child( maybeClone( other.child ) ) {
+}
+
+QualifiedType::~QualifiedType() {
+	delete parent;
+	delete child;
+}
+
+void QualifiedType::print( std::ostream & os, Indenter indent ) const {
+	os << "Qualified Type: " << endl;
+	os << indent+1;
+	parent->print( os, indent+1 );
+	os << endl << indent+1;
+	child->print( os, indent+1 );
+	os << endl;
+	Type::print( os, indent+1 );
+}
+
+GlobalScopeType::GlobalScopeType() : Type( Type::Qualifiers(), {} ) {}
+
+void GlobalScopeType::print( std::ostream & os, Indenter ) const {
+	os << "Global Scope Type" << endl;
+}
+
+
 // Empty Variable declarations:
 const Type::FuncSpecifiers noFuncSpecifiers;
Index: src/SynTree/Type.h
===================================================================
--- src/SynTree/Type.h	(revision bbe1a87944804b0f3c9e486087ca6af21340e747)
+++ src/SynTree/Type.h	(revision e3b24743580e0faaf833a980c334820f77cfefaf)
@@ -178,5 +178,5 @@
 	virtual bool isComplete() const { return true; }
 
-	virtual AggregateDecl * getAggr() { assertf( false, "Non-aggregate type: %s", toCString( this ) ); }
+	virtual AggregateDecl * getAggr() const { assertf( false, "Non-aggregate type: %s", toCString( this ) ); }
 
 	virtual TypeSubstitution genericSubstitution() const;
@@ -315,4 +315,19 @@
 };
 
+class QualifiedType : public Type {
+public:
+	Type * parent;
+	Type * child;
+
+	QualifiedType( const Type::Qualifiers & tq, Type * parent, Type * child );
+	QualifiedType( const QualifiedType & tq );
+	virtual ~QualifiedType();
+
+	virtual QualifiedType *clone() const override { return new QualifiedType( *this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
+};
+
 class ReferenceType : public Type {
 public:
@@ -416,5 +431,5 @@
 	virtual bool isComplete() const override;
 
-	virtual AggregateDecl * getAggr() override;
+	virtual AggregateDecl * getAggr() const override;
 
 	virtual TypeSubstitution genericSubstitution() const override;
@@ -453,5 +468,5 @@
 	virtual bool isComplete() const override;
 
-	virtual AggregateDecl * getAggr() override;
+	virtual AggregateDecl * getAggr() const override;
 
 	virtual TypeSubstitution genericSubstitution() const override;
@@ -485,4 +500,6 @@
 
 	virtual bool isComplete() const override;
+
+	virtual AggregateDecl * getAggr() const;
 
 	virtual EnumInstType *clone() const override { return new EnumInstType( *this ); }
@@ -665,4 +682,14 @@
 };
 
+class GlobalScopeType : public Type {
+  public:
+	GlobalScopeType();
+
+	virtual GlobalScopeType *clone() const override { return new GlobalScopeType( *this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
+};
+
 // Local Variables: //
 // tab-width: 4 //
Index: src/SynTree/Visitor.h
===================================================================
--- src/SynTree/Visitor.h	(revision bbe1a87944804b0f3c9e486087ca6af21340e747)
+++ src/SynTree/Visitor.h	(revision e3b24743580e0faaf833a980c334820f77cfefaf)
@@ -103,4 +103,5 @@
 	virtual void visit( ArrayType * arrayType ) = 0;
 	virtual void visit( ReferenceType * refType ) = 0;
+	virtual void visit( QualifiedType * qualType ) = 0;
 	virtual void visit( FunctionType * functionType ) = 0;
 	virtual void visit( StructInstType * aggregateUseType ) = 0;
@@ -115,4 +116,5 @@
 	virtual void visit( ZeroType * zeroType ) = 0;
 	virtual void visit( OneType * oneType ) = 0;
+	virtual void visit( GlobalScopeType * globalType ) = 0;
 
 	virtual void visit( Designation * designation ) = 0;
Index: src/prelude/prelude.cf
===================================================================
--- src/prelude/prelude.cf	(revision bbe1a87944804b0f3c9e486087ca6af21340e747)
+++ src/prelude/prelude.cf	(revision e3b24743580e0faaf833a980c334820f77cfefaf)
@@ -728,5 +728,4 @@
 forall( dtype DT ) void ?{}(	   volatile  DT *	   &,			DT * );
 forall( dtype DT ) void ?{}(	   volatile  DT *	   &,	    volatile	DT * );
-
 forall( dtype DT ) void ?{}( const volatile  DT *	   &,			DT * );
 forall( dtype DT ) void ?{}( const volatile  DT *	   &, const		DT * );
