Index: src/ResolvExpr/ResolveTypeof.cc
===================================================================
--- src/ResolvExpr/ResolveTypeof.cc	(revision fb2bde4553a732a870257c4906b0edd14740a6e5)
+++ src/ResolvExpr/ResolveTypeof.cc	(revision e98c7ab8e4ef76d28a872e441e8ec07ed2328e28)
@@ -18,5 +18,11 @@
 #include <cassert>               // for assert
 
+#include "AST/CVQualifiers.hpp"
+#include "AST/Node.hpp"
+#include "AST/Pass.hpp"
+#include "AST/Type.hpp"
+#include "AST/TypeEnvironment.hpp"
 #include "Common/PassVisitor.h"  // for PassVisitor
+#include "Common/utility.h"      // for copy
 #include "Resolver.h"            // for resolveInVoidContext
 #include "SynTree/Expression.h"  // for Expression
@@ -42,7 +48,7 @@
 	}
 
-	class ResolveTypeof : public WithShortCircuiting {
+	class ResolveTypeof_old : public WithShortCircuiting {
 	  public:
-		ResolveTypeof( const SymTab::Indexer &indexer ) : indexer( indexer ) {}
+		ResolveTypeof_old( const SymTab::Indexer &indexer ) : indexer( indexer ) {}
 		void premutate( TypeofType *typeofType );
 		Type * postmutate( TypeofType *typeofType );
@@ -53,13 +59,13 @@
 
 	Type * resolveTypeof( Type *type, const SymTab::Indexer &indexer ) {
-		PassVisitor<ResolveTypeof> mutator( indexer );
+		PassVisitor<ResolveTypeof_old> mutator( indexer );
 		return type->acceptMutator( mutator );
 	}
 
-	void ResolveTypeof::premutate( TypeofType * ) {
+	void ResolveTypeof_old::premutate( TypeofType * ) {
 		visit_children = false;
 	}
 
-	Type * ResolveTypeof::postmutate( TypeofType *typeofType ) {
+	Type * ResolveTypeof_old::postmutate( TypeofType *typeofType ) {
 #if 0
 		std::cerr << "resolving typeof: ";
@@ -108,10 +114,53 @@
 	}
 
-	const ast::Type * resolveTypeof( const ast::Type * type , const ast::SymbolTable & symtab ) {
-		#warning unimplemented
-		(void)type; (void)symtab;
-		assert(false);
-		return nullptr;
-	}
+namespace {
+	struct ResolveTypeof_new : public ast::WithShortCircuiting {
+		const ast::SymbolTable & localSymtab;
+
+		ResolveTypeof_new( const ast::SymbolTable & syms ) : localSymtab( syms ) {}
+
+		void premutate( const ast::TypeofType * ) { visit_children = false; }
+
+		const ast::Type * postmutate( const ast::TypeofType * typeofType ) {
+			// pass on null expression
+			if ( ! typeofType->expr ) return typeofType;
+
+			ast::ptr< ast::Type > newType;
+			if ( auto tyExpr = typeofType->expr.as< ast::TypeExpr >() ) {
+				// typeof wrapping type
+				newType = tyExpr->type;
+			} else {
+				// typeof wrapping expression
+				ast::TypeEnvironment dummy;
+				ast::ptr< ast::Expr > newExpr = 
+					resolveInVoidContext( typeofType->expr, localSymtab, dummy );
+				assert( newExpr->result && ! newExpr->result->isVoid() );
+				newType = newExpr->result;
+			}
+
+			// clear qualifiers for base, combine with typeoftype quals regardless
+			if ( typeofType->kind == ast::TypeofType::Basetypeof ) {
+				// replace basetypeof(<enum>) by int
+				if ( newType.as< ast::EnumInstType >() ) {
+					newType = new ast::BasicType{ 
+						ast::BasicType::SignedInt, newType->qualifiers, copy(newType->attributes) };
+				}
+				reset_qualifiers( 
+					newType, 
+					( newType->qualifiers & ~ast::CV::EquivQualifiers ) | typeofType->qualifiers );
+			} else {
+				add_qualifiers( newType, typeofType->qualifiers );
+			}
+
+			return newType;
+		}
+	};
+} // anonymous namespace
+
+const ast::Type * resolveTypeof( const ast::Type * type , const ast::SymbolTable & symtab ) {
+	ast::Pass< ResolveTypeof_new > mutator{ symtab };
+	return type->accept( mutator );
+}
+
 } // namespace ResolvExpr
 
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision fb2bde4553a732a870257c4906b0edd14740a6e5)
+++ src/ResolvExpr/Resolver.cc	(revision e98c7ab8e4ef76d28a872e441e8ec07ed2328e28)
@@ -1226,6 +1226,6 @@
 		const ast::StaticAssertDecl * previsit( const ast::StaticAssertDecl * );
 
-		void previsit( const ast::ArrayType * );
-		void previsit( const ast::PointerType * );
+		const ast::ArrayType * previsit( const ast::ArrayType * );
+		const ast::PointerType * previsit( const ast::PointerType * );
 
 		const ast::ExprStmt *        previsit( const ast::ExprStmt * );
@@ -1334,16 +1334,22 @@
 
 	template< typename PtrType >
-	void handlePtrType( const PtrType * type, const ast::SymbolTable & symtab ) {
-		#warning unimplemented; needs support for new Validate::SizeType global
-		(void)type; (void)symtab;
-		assert( false );
-	}
-
-	void Resolver_new::previsit( const ast::ArrayType * at ) {
-		handlePtrType( at, symtab );
-	}
-
-	void Resolver_new::previsit( const ast::PointerType * pt ) {
-		handlePtrType( pt, symtab );
+	const PtrType * handlePtrType( const PtrType * type, const ast::SymbolTable & symtab ) {
+		if ( type->dimension ) {
+			#warning should use new equivalent to Validate::SizeType rather than sizeType here
+			ast::ptr< ast::Type > sizeType = 
+				new ast::BasicType{ ast::BasicType::LongLongUnsignedInt };
+			ast::mutate_field( 
+				type, &PtrType::dimension, 
+				findSingleExpression( type->dimension, sizeType, symtab ) );
+		}
+		return type;
+	}
+
+	const ast::ArrayType * Resolver_new::previsit( const ast::ArrayType * at ) {
+		return handlePtrType( at, symtab );
+	}
+
+	const ast::PointerType * Resolver_new::previsit( const ast::PointerType * pt ) {
+		return handlePtrType( pt, symtab );
 	}
 
