Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision 7756647eaf7d18e5f8c8c4841b9279a5f4e4f8dc)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision 848ce7101657d18db026ce010e05ae0026f97f55)
@@ -229,4 +229,20 @@
 			assertf( false, "reached unexpected case of addAggMembers" );
 		}
+	}
+
+	void AlternativeFinder::addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
+		if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) {
+			// get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning
+			// xxx - this should be improved by memoizing the value of constant exprs
+			// during parsing and reusing that information here.
+			std::stringstream ss( constantExpr->get_constant()->get_value() );
+			int val;
+			std::string tmp;
+			if ( ss >> val && ! (ss >> tmp) ) {
+				if ( val >= 0 && (unsigned int)val < tupleType->size() ) {
+					alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );
+				} // if
+			} // if
+		} // if
 	}
 
@@ -785,4 +801,6 @@
 			} else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( agg->expr->get_result() ) ) {
 				addAggMembers( unionInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
+			} else if ( TupleType * tupleType = dynamic_cast< TupleType * >( agg->expr->get_result() ) ) {
+				addTupleMembers( tupleType, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
 			} // if
 		} // for
Index: src/ResolvExpr/AlternativeFinder.h
===================================================================
--- src/ResolvExpr/AlternativeFinder.h	(revision 7756647eaf7d18e5f8c8c4841b9279a5f4e4f8dc)
+++ src/ResolvExpr/AlternativeFinder.h	(revision 848ce7101657d18db026ce010e05ae0026f97f55)
@@ -76,4 +76,6 @@
 		/// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member
 		template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member );
+		/// Adds alternatives for member expressions where the left side has tuple type
+		void addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member );
 		/// Adds alternatives for offsetof expressions, given the base type and name of the member
 		template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name );
