Index: src/SymTab/Indexer.cc
===================================================================
--- src/SymTab/Indexer.cc	(revision 12d2dc8fad3691528e0f541fe5bd38046cdc9877)
+++ src/SymTab/Indexer.cc	(revision 6ba16faa70d742f593c53205ee3a02a30e15dd1c)
@@ -40,5 +40,9 @@
 
 namespace SymTab {
-	typedef std::unordered_map< std::string, DeclarationWithType* > MangleTable;
+	std::ostream & operator<<( std::ostream & out, const Indexer::IdData & data ) {
+		return out << "(" << data.id << "," << data.baseExpr << ")";
+	}
+
+	typedef std::unordered_map< std::string, Indexer::IdData > MangleTable;
 	typedef std::unordered_map< std::string, MangleTable > IdTable;
 	typedef std::unordered_map< std::string, NamedTypeDecl* > TypeTable;
@@ -97,5 +101,5 @@
 	}
 
-	void Indexer::removeSpecialOverrides( const std::string &id, std::list< DeclarationWithType * > & out ) const {
+	void Indexer::removeSpecialOverrides( const std::string &id, std::list< IdData > & out ) const {
 		// only need to perform this step for constructors, destructors, and assignment functions
 		if ( ! CodeGen::isCtorDtorAssign( id ) ) return;
@@ -104,5 +108,5 @@
 		struct ValueType {
 			struct DeclBall {
-				FunctionDecl * decl;
+				IdData decl;
 				bool isUserDefinedFunc; // properties for this particular decl
 				bool isDefaultCtor;
@@ -120,10 +124,11 @@
 			// another FunctionDecl for the current type was found - determine
 			// if it has special properties and update data structure accordingly
-			ValueType & operator+=( FunctionDecl * function ) {
+			ValueType & operator+=( IdData data ) {
+				DeclarationWithType * function = data.id;
 				bool isUserDefinedFunc = ! LinkageSpec::isOverridable( function->get_linkage() );
 				bool isDefaultCtor = InitTweak::isDefaultConstructor( function );
 				bool isDtor = InitTweak::isDestructor( function );
 				bool isCopyFunc = InitTweak::isCopyFunction( function, function->get_name() );
-				decls.push_back( DeclBall{ function, isUserDefinedFunc, isDefaultCtor, isDtor, isCopyFunc } );
+				decls.push_back( DeclBall{ data, isUserDefinedFunc, isDefaultCtor, isDtor, isCopyFunc } );
 				existsUserDefinedFunc = existsUserDefinedFunc || isUserDefinedFunc;
 				existsUserDefinedCtor = existsUserDefinedCtor || (isUserDefinedFunc && CodeGen::isConstructor( function->get_name() ) );
@@ -135,11 +140,11 @@
 		}; // ValueType
 
-		std::list< DeclarationWithType * > copy;
+		std::list< IdData > copy;
 		copy.splice( copy.end(), out );
 
 		// organize discovered declarations by type
 		std::unordered_map< std::string, ValueType > funcMap;
-		for ( DeclarationWithType * decl : copy ) {
-			if ( FunctionDecl * function = dynamic_cast< FunctionDecl * >( decl ) ) {
+		for ( auto decl : copy ) {
+			if ( FunctionDecl * function = dynamic_cast< FunctionDecl * >( decl.id ) ) {
 				std::list< DeclarationWithType * > & params = function->get_functionType()->get_parameters();
 				assert( ! params.empty() );
@@ -147,5 +152,5 @@
 				Type * base = InitTweak::getPointerBase( params.front()->get_type() );
 				assert( base );
-				funcMap[ Mangler::mangle( base ) ] += function;
+				funcMap[ Mangler::mangle( base ) ] += decl;
 			} else {
 				out.push_back( decl );
@@ -164,5 +169,5 @@
 				bool noUserDefinedFunc = ! val.existsUserDefinedFunc;
 				bool isUserDefinedFunc = ball.isUserDefinedFunc;
-				bool isAcceptableDefaultCtor = (! val.existsUserDefinedCtor || (! val.existsUserDefinedDefaultCtor && ball.decl->get_linkage() == LinkageSpec::Intrinsic)) && ball.isDefaultCtor; // allow default constructors only when no user-defined constructors exist, except in the case of intrinsics, which require exact overrides
+				bool isAcceptableDefaultCtor = (! val.existsUserDefinedCtor || (! val.existsUserDefinedDefaultCtor && ball.decl.id->get_linkage() == LinkageSpec::Intrinsic)) && ball.isDefaultCtor; // allow default constructors only when no user-defined constructors exist, except in the case of intrinsics, which require exact overrides
 				bool isAcceptableCopyFunc = ! val.existsUserDefinedCopyFunc && ball.isCopyFunc; // handles copy ctor and assignment operator
 				bool isAcceptableDtor = ! val.existsUserDefinedDtor && ball.isDtor;
@@ -219,5 +224,5 @@
 	}
 
-	void Indexer::lookupId( const std::string &id, std::list< DeclarationWithType* > &out ) const {
+	void Indexer::lookupId( const std::string &id, std::list< IdData > &out ) const {
 		std::unordered_set< std::string > foundMangleNames;
 
@@ -289,5 +294,5 @@
 			const MangleTable &mangleTable = decls->second;
 			MangleTable::const_iterator decl = mangleTable.find( mangleName );
-			if ( decl != mangleTable.end() ) return decl->second;
+			if ( decl != mangleTable.end() ) return decl->second.id;
 		}
 
@@ -304,5 +309,5 @@
 			for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) {
 				// check for C decls with the same name, skipping those with a compatible type (by mangleName)
-				if ( ! LinkageSpec::isMangled( decl->second->get_linkage() ) && decl->first != mangleName ) return true;
+				if ( ! LinkageSpec::isMangled( decl->second.id->get_linkage() ) && decl->first != mangleName ) return true;
 			}
 		}
@@ -321,5 +326,5 @@
 				// check for C decls with the same name, skipping
 				// those with an incompatible type (by mangleName)
-				if ( ! LinkageSpec::isMangled( decl->second->get_linkage() ) && decl->first == mangleName ) return true;
+				if ( ! LinkageSpec::isMangled( decl->second.id->get_linkage() ) && decl->first == mangleName ) return true;
 			}
 		}
@@ -403,5 +408,5 @@
 	}
 
-	void Indexer::addId( DeclarationWithType *decl ) {
+	void Indexer::addId( DeclarationWithType *decl, Expression * baseExpr ) {
 		debugPrint( "Adding Id " << decl->name << std::endl );
 		makeWritable();
@@ -439,5 +444,5 @@
 
 		// add to indexer
-		tables->idTable[ name ][ mangleName ] = decl;
+		tables->idTable[ name ][ mangleName ] = { decl, baseExpr };
 		++tables->size;
 	}
@@ -563,4 +568,19 @@
 			if ( ! addedDeclConflicts( existing->second, decl ) ) {
 				existing->second = decl;
+			}
+		}
+	}
+
+	void Indexer::addWith( WithStmt * stmt ) {
+		for ( Expression * expr : stmt->exprs ) {
+			if ( expr->result ) {
+				AggregateDecl * aggr = expr->result->stripReferences()->getAggr();
+				assertf( aggr, "WithStmt expr has non-aggregate type: %s", toString( expr->result ).c_str() );
+
+				for ( Declaration * decl : aggr->members ) {
+					if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) {
+						addId( dwt, expr );
+					}
+				}
 			}
 		}
@@ -645,4 +665,19 @@
 
 	}
+
+	Expression * Indexer::IdData::combine() const {
+		if ( baseExpr ) {
+			Expression * base = baseExpr->clone();
+			ResolvExpr::referenceToRvalueConversion( base );
+			Expression * ret = new MemberExpr( id, base );
+			// xxx - this introduces hidden environments, for now remove them.
+			// std::swap( base->env, ret->env );
+			delete base->env;
+			base->env = nullptr;
+			return ret;
+		} else {
+			return new VariableExpr( id );
+		}
+	}
 } // namespace SymTab
 
Index: src/SymTab/Indexer.h
===================================================================
--- src/SymTab/Indexer.h	(revision 12d2dc8fad3691528e0f541fe5bd38046cdc9877)
+++ src/SymTab/Indexer.h	(revision 6ba16faa70d742f593c53205ee3a02a30e15dd1c)
@@ -39,6 +39,13 @@
 		void leaveScope();
 
+		struct IdData {
+			DeclarationWithType * id;
+			Expression * baseExpr; // WithExpr
+
+			Expression * combine() const;
+		};
+
 		/// Gets all declarations with the given ID
-		void lookupId( const std::string &id, std::list< DeclarationWithType* > &out ) const;
+		void lookupId( const std::string &id, std::list< IdData > &out ) const;
 		/// Gets the top-most type declaration with the given ID
 		NamedTypeDecl *lookupType( const std::string &id ) const;
@@ -67,5 +74,5 @@
 		TraitDecl *lookupTraitAtScope( const std::string &id, unsigned long scope ) const;
 
-		void addId( DeclarationWithType *decl );
+		void addId( DeclarationWithType *decl, Expression * baseExpr = nullptr );
 		void addType( NamedTypeDecl *decl );
 		void addStruct( const std::string &id );
@@ -75,4 +82,7 @@
 		void addUnion( UnionDecl *decl );
 		void addTrait( TraitDecl *decl );
+
+		/// adds all of the IDs from WithStmt exprs
+		void addWith( WithStmt * );
 
 		/// convenience function for adding a list of Ids to the indexer
@@ -100,5 +110,5 @@
 		// so that they will not be selected
 		// void removeSpecialOverrides( FunctionDecl *decl );
-		void removeSpecialOverrides( const std::string &id, std::list< DeclarationWithType * > & out ) const;
+		void removeSpecialOverrides( const std::string &id, std::list< IdData > & out ) const;
 
 		/// Ensures that tables variable is writable (i.e. allocated, uniquely owned by this Indexer, and at the current scope)
