Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 49e1275f9e47ba4835e844ba251e13196033312a)
+++ src/SymTab/Validate.cc	(revision 062e8df6b7bfeda5076f3a78100f203e2752fdf8)
@@ -351,27 +351,19 @@
 
 	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 ) ) {
+			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() );
+				if ( ! td ) {
+					SemanticError( qualType->location, toString("Use of undefined global type ", inst->name) );
+				}
 				auto base = td->base;
-				if ( base ) return td->base->clone();
-				assert( false );
+				assert( base );
+				return base->clone();
 			} else {
-				// .T => T is not a SUE type name
-				assert( false );
+				// .T => T is not a type name
+				assertf( false, "unhandled global qualified child type: %s", toCString(child) );
 			}
 		} else {
@@ -383,5 +375,5 @@
 				aggr = inst->baseUnion;
 			} else {
-				assert( false );
+				SemanticError( qualType->location, toString("Qualified type requires an aggregate on the left, but has: ", parent) );
 			}
 			assert( aggr ); // TODO: need to handle forward declarations
@@ -409,6 +401,6 @@
 					if ( NamedTypeDecl * aggr = dynamic_cast< NamedTypeDecl * > ( member ) ) {
 						if ( aggr->name == inst->name ) {
-							if ( aggr->base ) return aggr->base->clone();
-							assert( false );
+							assert( aggr->base );
+							return aggr->base->clone();
 						}
 					}
@@ -419,5 +411,5 @@
 			}
 			// failed to find a satisfying definition of type
-			assertf( false, "failed to find a satisfying definition of %s in %s", toCString(child), toCString(parent) );
+			SemanticError( qualType->location, toString("Undefined type in qualified type: ", qualType) );
 		}
 
@@ -919,8 +911,11 @@
 		} else {
 			TypeDeclMap::const_iterator base = typedeclNames.find( typeInst->name );
-			assertf( base != typedeclNames.end(), "Cannot find typedecl name %s", typeInst->name.c_str() );
+			if ( base == typedeclNames.end() ) {
+				SemanticError( typeInst->location, toString("Use of undefined type ", typeInst->name) );
+			}
 			typeInst->set_baseType( base->second );
-		} // if
-		return typeInst;
+			return typeInst;
+		} // if
+		assert( false );
 	}
 
