Index: src/Parser/DeclarationNode.cc
===================================================================
--- src/Parser/DeclarationNode.cc	(revision 4c3ee8d83b18fa8870e0a924b814efd4ec1730fa)
+++ 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 4c3ee8d83b18fa8870e0a924b814efd4ec1730fa)
+++ 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 4c3ee8d83b18fa8870e0a924b814efd4ec1730fa)
+++ 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 4c3ee8d83b18fa8870e0a924b814efd4ec1730fa)
+++ 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 4c3ee8d83b18fa8870e0a924b814efd4ec1730fa)
+++ 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
 	;
