Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision 95642c922af6320ebcc6f75f52778865ecf6ff19)
+++ src/ResolvExpr/Resolver.cc	(revision cdb990a3f4e49d6faf7cbdf00fb2350033fd78cb)
@@ -127,7 +127,26 @@
 
 	namespace {
-		void finishExpr( Expression *expr, const TypeEnvironment &env, TypeSubstitution * oldenv = nullptr ) {
+		struct StripCasts {
+			Expression * postmutate( CastExpr * castExpr ) {
+				if ( castExpr->isGenerated && ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, SymTab::Indexer() ) ) {
+					// generated cast is to the same type as its argument, so it's unnecessary -- remove it
+					Expression * expr = castExpr->arg;
+					castExpr->arg = nullptr;
+					std::swap( expr->env, castExpr->env );
+					return expr;
+				}
+				return castExpr;
+			}
+
+			static void strip( Expression *& expr ) {
+				PassVisitor<StripCasts> stripper;
+				expr = expr->acceptMutator( stripper );
+			}
+		};
+
+		void finishExpr( Expression *&expr, const TypeEnvironment &env, TypeSubstitution * oldenv = nullptr ) {
 			expr->env = oldenv ? oldenv->clone() : new TypeSubstitution;
-			env.makeSubstitution( *expr->get_env() );
+			env.makeSubstitution( *expr->env );
+			StripCasts::strip( expr ); // remove unnecessary casts that may be buried in an expression
 		}
 
@@ -414,5 +433,5 @@
 
 	void Resolver::previsit( CaseStmt *caseStmt ) {
-		if ( caseStmt->get_condition() ) {
+		if ( caseStmt->condition ) {
 			std::list< InitAlternative > initAlts = currentObject.getOptions();
 			assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral expression." );
@@ -420,8 +439,13 @@
 			Expression * newExpr = new CastExpr( caseStmt->condition, initAlts.front().type->clone() );
 			findSingleExpression( newExpr, indexer );
-			CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( newExpr );
-			caseStmt->condition = castExpr->arg;
-			castExpr->arg = nullptr;
-			delete castExpr;
+			// case condition cannot have a cast in C, so it must be removed, regardless of whether it performs a conversion.
+			// Ideally we would perform the conversion internally here.
+			if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( newExpr ) ) {
+				newExpr = castExpr->arg;
+				castExpr->arg = nullptr;
+				std::swap( newExpr->env, castExpr->env );
+				delete castExpr;
+			}
+			caseStmt->condition = newExpr;
 		}
 	}
@@ -718,5 +742,7 @@
 		initExpr->expr = nullptr;
 		std::swap( initExpr->env, newExpr->env );
-		std::swap( initExpr->inferParams, newExpr->inferParams ) ;
+		// InitExpr may have inferParams in the case where the expression specializes a function pointer,
+		// and newExpr may already have inferParams of its own, so a simple swap is not sufficient.
+		newExpr->spliceInferParams( initExpr );
 		delete initExpr;
 
