Index: src/CodeGen/GenType.cc
===================================================================
--- src/CodeGen/GenType.cc	(revision f7cb0bc76af10982d6f4f34f060acc53a8dc27f9)
+++ src/CodeGen/GenType.cc	(revision b1e63ac54a1b3b3705d130858c9772e8b84c867f)
@@ -37,4 +37,5 @@
 		virtual void visit( PointerType *pointerType );
 		virtual void visit( ArrayType *arrayType );
+		virtual void visit( ReferenceType *refType );
 		virtual void visit( StructInstType *structInst );
 		virtual void visit( UnionInstType *unionInst );
@@ -147,4 +148,12 @@
 	}
 
+	void GenType::visit( ReferenceType *refType ) {
+		assert( refType->get_base() != 0);
+		assertf( ! genC, "Reference types should not reach code generation." );
+		handleQualifiers( refType );
+		typeString = "&" + typeString;
+		refType->get_base()->accept( *this );
+	}
+
 	void GenType::visit( FunctionType *funcType ) {
 		std::ostringstream os;
Index: src/Concurrency/Keywords.cc
===================================================================
--- src/Concurrency/Keywords.cc	(revision f7cb0bc76af10982d6f4f34f060acc53a8dc27f9)
+++ src/Concurrency/Keywords.cc	(revision b1e63ac54a1b3b3705d130858c9772e8b84c867f)
@@ -322,5 +322,5 @@
 		if( needs_main ) {
 			FunctionType * main_type = new FunctionType( noQualifiers, false );
-			
+
 			main_type->get_parameters().push_back( this_decl->clone() );
 
@@ -361,5 +361,5 @@
 	void ConcurrentSueKeyword::addRoutines( ObjectDecl * field, FunctionDecl * func ) {
 		CompoundStmt * statement = new CompoundStmt( noLabels );
-		statement->push_back( 
+		statement->push_back(
 			new ReturnStmt(
 				noLabels,
@@ -386,5 +386,5 @@
 	//=============================================================================================
 	void MutexKeyword::visit(FunctionDecl* decl) {
-		Visitor::visit(decl);		
+		Visitor::visit(decl);
 
 		std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl );
@@ -510,11 +510,9 @@
 	void ThreadStarter::visit(FunctionDecl * decl) {
 		Visitor::visit(decl);
-		
+
 		if( ! InitTweak::isConstructor(decl->get_name()) ) return;
 
 		DeclarationWithType * param = decl->get_functionType()->get_parameters().front();
-		auto ptr = dynamic_cast< PointerType * >( param->get_type() );
-		// if( ptr ) std::cerr << "FRED1" << std::endl;
-		auto type  = dynamic_cast< StructInstType * >( ptr->get_base() );
+		auto type  = dynamic_cast< StructInstType * >( InitTweak::getPointerBase( param->get_type() ) );
 		// if( type ) std::cerr << "FRED2" << std::endl;
 		if( type && type->get_baseStruct()->is_thread() ) {
@@ -528,5 +526,5 @@
 		if( ! stmt ) return;
 
-		stmt->push_back( 
+		stmt->push_back(
 			new ExprStmt(
 				noLabels,
Index: src/GenPoly/Lvalue.cc
===================================================================
--- src/GenPoly/Lvalue.cc	(revision f7cb0bc76af10982d6f4f34f060acc53a8dc27f9)
+++ src/GenPoly/Lvalue.cc	(revision b1e63ac54a1b3b3705d130858c9772e8b84c867f)
@@ -32,4 +32,5 @@
 #include "Common/UniqueName.h"
 #include "Common/utility.h"
+#include "InitTweak/InitTweak.h"
 
 namespace GenPoly {
@@ -38,6 +39,10 @@
 		class Pass1 : public Mutator {
 		  public:
+			typedef Mutator Parent;
 			Pass1();
 
+			// xxx - should this happen to every expression with reference result type? probably just appexpr and varexpr?
+			virtual Type *mutate( ReferenceType * refType );
+			virtual Expression *mutate( VariableExpr *varExpr );
 			virtual Expression *mutate( ApplicationExpr *appExpr );
 			virtual Statement *mutate( ReturnStmt *appExpr );
@@ -103,4 +108,19 @@
 			} // if
 			return funcDecl;
+		}
+
+		Type * Pass1::mutate( ReferenceType * refType ) {
+			Type * base = refType->get_base();
+			refType->set_base( nullptr );
+			delete refType;
+			return new PointerType( Type::Qualifiers(), base );
+		}
+
+		Expression * Pass1::mutate( VariableExpr *varExpr ) {
+			if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( varExpr->get_result() ) ) {
+				varExpr->set_result( refType->acceptMutator( *this ) );
+				return UntypedExpr::createDeref( varExpr );
+			}
+			return Parent::mutate( varExpr );
 		}
 
@@ -163,4 +183,14 @@
 		}
 
+		bool isDeref( Expression * expr ) {
+			if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) {
+				return InitTweak::getFunctionName( untyped ) == "*?";
+			} else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) {
+				return InitTweak::getFunctionName( appExpr ) == "*?";
+			} else {
+				return false;
+			}
+		}
+
 		Expression * GeneralizedLvalue::mutate( AddressExpr * addrExpr ) {
 			addrExpr = safe_dynamic_cast< AddressExpr * >( Parent::mutate( addrExpr ) );
@@ -176,4 +206,11 @@
 				delete addrExpr;
 				return new ConditionalExpr( arg1, new AddressExpr( arg2 ), new AddressExpr( arg3 ) );
+			} else if ( isDeref( addrExpr->get_arg() ) ) {
+				// xxx - this doesn't belong here -- move it somewhere else
+				Expression *& arg = InitTweak::getCallArg( addrExpr->get_arg(), 0 );
+				Expression * inner = arg;
+				arg = nullptr;
+				delete addrExpr;
+				return inner;
 			}
 			return addrExpr;
Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision f7cb0bc76af10982d6f4f34f060acc53a8dc27f9)
+++ src/InitTweak/FixInit.cc	(revision b1e63ac54a1b3b3705d130858c9772e8b84c867f)
@@ -401,5 +401,5 @@
 
 		bool ResolveCopyCtors::skipCopyConstruct( Type * type ) {
-			return dynamic_cast< VarArgsType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type );
+			return dynamic_cast< VarArgsType * >( type ) || dynamic_cast< ReferenceType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type );
 		}
 
Index: src/InitTweak/GenInit.cc
===================================================================
--- src/InitTweak/GenInit.cc	(revision f7cb0bc76af10982d6f4f34f060acc53a8dc27f9)
+++ src/InitTweak/GenInit.cc	(revision b1e63ac54a1b3b3705d130858c9772e8b84c867f)
@@ -239,6 +239,7 @@
 			std::list< DeclarationWithType * > & params = GenPoly::getFunctionType( dwt->get_type() )->get_parameters();
 			assert( ! params.empty() );
-			PointerType * type = safe_dynamic_cast< PointerType * >( params.front()->get_type() );
-			managedTypes.insert( SymTab::Mangler::mangle( type->get_base() ) );
+			Type * type = InitTweak::getPointerBase( params.front()->get_type() );
+			assert( type );
+			managedTypes.insert( SymTab::Mangler::mangle( type ) );
 		}
 	}
Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision f7cb0bc76af10982d6f4f34f060acc53a8dc27f9)
+++ src/InitTweak/InitTweak.cc	(revision b1e63ac54a1b3b3705d130858c9772e8b84c867f)
@@ -458,4 +458,6 @@
 		} else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
 			return arrayType->get_base();
+		} else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( type ) ) {
+			return refType->get_base();
 		} else {
 			return NULL;
@@ -543,10 +545,9 @@
 		if ( ftype->get_parameters().size() != 2 ) return 0;
 
-		Type * t1 = ftype->get_parameters().front()->get_type();
+		Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() );
 		Type * t2 = ftype->get_parameters().back()->get_type();
-		PointerType * ptrType = dynamic_cast< PointerType * > ( t1 );
-		assert( ptrType );
-
-		if ( ResolvExpr::typesCompatibleIgnoreQualifiers( ptrType->get_base(), t2, SymTab::Indexer() ) ) {
+		assert( t1 );
+
+		if ( ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, SymTab::Indexer() ) ) {
 			return function;
 		} else {
Index: src/Parser/DeclarationNode.cc
===================================================================
--- src/Parser/DeclarationNode.cc	(revision f7cb0bc76af10982d6f4f34f060acc53a8dc27f9)
+++ src/Parser/DeclarationNode.cc	(revision b1e63ac54a1b3b3705d130858c9772e8b84c867f)
@@ -329,7 +329,7 @@
 } // DeclarationNode::newTypeDecl
 
-DeclarationNode * DeclarationNode::newPointer( DeclarationNode * qualifiers ) {
-	DeclarationNode * newnode = new DeclarationNode;
-	newnode->type = new TypeData( TypeData::Pointer );
+DeclarationNode * DeclarationNode::newPointer( DeclarationNode * qualifiers, OperKinds kind ) {
+	DeclarationNode * newnode = new DeclarationNode;
+	newnode->type = new TypeData( kind == OperKinds::PointTo ? TypeData::Pointer : TypeData::Reference );
 	if ( qualifiers ) {
 		return newnode->addQualifiers( qualifiers );
@@ -748,5 +748,5 @@
 DeclarationNode * DeclarationNode::addPointer( DeclarationNode * p ) {
 	if ( p ) {
-		assert( p->type->kind == TypeData::Pointer );
+		assert( p->type->kind == TypeData::Pointer || TypeData::Reference );
 		setBase( p->type );
 		p->type = nullptr;
Index: src/Parser/ParseNode.h
===================================================================
--- src/Parser/ParseNode.h	(revision f7cb0bc76af10982d6f4f34f060acc53a8dc27f9)
+++ src/Parser/ParseNode.h	(revision b1e63ac54a1b3b3705d130858c9772e8b84c867f)
@@ -237,5 +237,5 @@
 	static DeclarationNode * newTraitUse( const std::string * name, ExpressionNode * params );
 	static DeclarationNode * newTypeDecl( std::string * name, DeclarationNode * typeParams );
-	static DeclarationNode * newPointer( DeclarationNode * qualifiers );
+	static DeclarationNode * newPointer( DeclarationNode * qualifiers, OperKinds kind );
 	static DeclarationNode * newArray( ExpressionNode * size, DeclarationNode * qualifiers, bool isStatic );
 	static DeclarationNode * newVarArray( DeclarationNode * qualifiers );
Index: src/Parser/TypeData.cc
===================================================================
--- src/Parser/TypeData.cc	(revision f7cb0bc76af10982d6f4f34f060acc53a8dc27f9)
+++ src/Parser/TypeData.cc	(revision b1e63ac54a1b3b3705d130858c9772e8b84c867f)
@@ -30,4 +30,5 @@
 	  case Unknown:
 	  case Pointer:
+	  case Reference:
 	  case EnumConstant:
 		// nothing else to initialize
@@ -99,4 +100,5 @@
 	  case Unknown:
 	  case Pointer:
+	  case Reference:
 	  case EnumConstant:
 		// nothing to destroy
@@ -165,4 +167,5 @@
 	  case EnumConstant:
 	  case Pointer:
+	  case Reference:
 		// nothing else to copy
 		break;
@@ -434,4 +437,6 @@
 	  case TypeData::Array:
 		return buildArray( td );
+	  case TypeData::Reference:
+		return buildReference( td );
 	  case TypeData::Function:
 		return buildFunction( td );
@@ -612,5 +617,16 @@
 	buildForall( td->forall, at->get_forall() );
 	return at;
-} // buildPointer
+} // buildArray
+
+ReferenceType * buildReference( const TypeData * td ) {
+	ReferenceType * rt;
+	if ( td->base ) {
+		rt = new ReferenceType( buildQualifiers( td ), typebuild( td->base ) );
+	} else {
+		rt = new ReferenceType( buildQualifiers( td ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
+	} // if
+	buildForall( td->forall, rt->get_forall() );
+	return rt;
+} // buildReference
 
 AggregateDecl * buildAggregate( const TypeData * td, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ) {
Index: src/Parser/TypeData.h
===================================================================
--- src/Parser/TypeData.h	(revision f7cb0bc76af10982d6f4f34f060acc53a8dc27f9)
+++ src/Parser/TypeData.h	(revision b1e63ac54a1b3b3705d130858c9772e8b84c867f)
@@ -21,5 +21,5 @@
 
 struct TypeData {
-	enum Kind { Basic, Pointer, Array, Function, Aggregate, AggregateInst, Enum, EnumConstant, Symbolic,
+	enum Kind { Basic, Pointer, Array, Reference, Function, Aggregate, AggregateInst, Enum, EnumConstant, Symbolic,
 				SymbolicInst, Tuple, Typeof, Builtin, Unknown };
 
@@ -101,4 +101,5 @@
 PointerType * buildPointer( const TypeData * );
 ArrayType * buildArray( const TypeData * );
+ReferenceType * buildReference( const TypeData * );
 AggregateDecl * buildAggregate( const TypeData *, std::list< Attribute * > );
 ReferenceToType * buildComAggInst( const TypeData *, std::list< Attribute * > attributes, LinkageSpec::Spec linkage );
Index: src/Parser/parser.yy
===================================================================
--- src/Parser/parser.yy	(revision f7cb0bc76af10982d6f4f34f060acc53a8dc27f9)
+++ src/Parser/parser.yy	(revision b1e63ac54a1b3b3705d130858c9772e8b84c867f)
@@ -2382,7 +2382,7 @@
 variable_ptr:
 	ptrref_operator variable_declarator
-		{ $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
+		{ $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
 	| ptrref_operator type_qualifier_list variable_declarator
-		{ $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
+		{ $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
 	| '(' variable_ptr ')' attribute_list_opt
 		{ $$ = $2->addQualifiers( $4 ); }				// redundant parenthesis
@@ -2430,7 +2430,7 @@
 function_ptr:
 	ptrref_operator function_declarator
-		{ $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
+		{ $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
 	| ptrref_operator type_qualifier_list function_declarator
-		{ $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
+		{ $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
 	| '(' function_ptr ')'
 		{ $$ = $2; }
@@ -2470,7 +2470,7 @@
 KR_function_ptr:
 	ptrref_operator KR_function_declarator
-		{ $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
+		{ $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
 	| ptrref_operator type_qualifier_list KR_function_declarator
-		{ $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
+		{ $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
 	| '(' KR_function_ptr ')'
 		{ $$ = $2; }
@@ -2514,7 +2514,7 @@
 type_ptr:
 	ptrref_operator variable_type_redeclarator
-		{ $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
+		{ $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
 	| ptrref_operator type_qualifier_list variable_type_redeclarator
-		{ $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
+		{ $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
 	| '(' type_ptr ')' attribute_list_opt
 		{ $$ = $2->addQualifiers( $4 ); }
@@ -2558,7 +2558,7 @@
 identifier_parameter_ptr:
 	ptrref_operator identifier_parameter_declarator
-		{ $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
+		{ $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
 	| ptrref_operator type_qualifier_list identifier_parameter_declarator
-		{ $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
+		{ $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
 	| '(' identifier_parameter_ptr ')' attribute_list_opt
 		{ $$ = $2->addQualifiers( $4 ); }
@@ -2618,7 +2618,7 @@
 type_parameter_ptr:
 	ptrref_operator type_parameter_redeclarator
-		{ $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
+		{ $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
 	| ptrref_operator type_qualifier_list type_parameter_redeclarator
-		{ $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
+		{ $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
 	| '(' type_parameter_ptr ')' attribute_list_opt
 		{ $$ = $2->addQualifiers( $4 ); }
@@ -2661,11 +2661,11 @@
 abstract_ptr:
 	ptrref_operator
-		{ $$ = DeclarationNode::newPointer( 0 ); }
+		{ $$ = DeclarationNode::newPointer( 0, $1 ); }
 	| ptrref_operator type_qualifier_list
-		{ $$ = DeclarationNode::newPointer( $2 ); }
+		{ $$ = DeclarationNode::newPointer( $2, $1 ); }
 	| ptrref_operator abstract_declarator
-		{ $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
+		{ $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
 	| ptrref_operator type_qualifier_list abstract_declarator
-		{ $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
+		{ $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
 	| '(' abstract_ptr ')' attribute_list_opt
 		{ $$ = $2->addQualifiers( $4 ); }
@@ -2750,11 +2750,11 @@
 abstract_parameter_ptr:
 	ptrref_operator
-		{ $$ = DeclarationNode::newPointer( nullptr ); }
+		{ $$ = DeclarationNode::newPointer( nullptr, $1 ); }
 	| ptrref_operator type_qualifier_list
-		{ $$ = DeclarationNode::newPointer( $2 ); }
+		{ $$ = DeclarationNode::newPointer( $2, $1 ); }
 	| ptrref_operator abstract_parameter_declarator
-		{ $$ = $2->addPointer( DeclarationNode::newPointer( nullptr ) ); }
+		{ $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
 	| ptrref_operator type_qualifier_list abstract_parameter_declarator
-		{ $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
+		{ $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
 	| '(' abstract_parameter_ptr ')' attribute_list_opt
 		{ $$ = $2->addQualifiers( $4 ); }
@@ -2829,11 +2829,11 @@
 variable_abstract_ptr:
 	ptrref_operator
-		{ $$ = DeclarationNode::newPointer( 0 ); }
+		{ $$ = DeclarationNode::newPointer( 0, $1 ); }
 	| ptrref_operator type_qualifier_list
-		{ $$ = DeclarationNode::newPointer( $2 ); }
+		{ $$ = DeclarationNode::newPointer( $2, $1 ); }
 	| ptrref_operator variable_abstract_declarator
-		{ $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
+		{ $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
 	| ptrref_operator type_qualifier_list variable_abstract_declarator
-		{ $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
+		{ $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
 	| '(' variable_abstract_ptr ')' attribute_list_opt
 		{ $$ = $2->addQualifiers( $4 ); }
@@ -2875,15 +2875,15 @@
 		// No SUE declaration in parameter list.
 	ptrref_operator type_specifier_nobody
-		{ $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
+		{ $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
 	| type_qualifier_list ptrref_operator type_specifier_nobody
-		{ $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
+		{ $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
 	| ptrref_operator cfa_abstract_function
-		{ $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
+		{ $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
 	| type_qualifier_list ptrref_operator cfa_abstract_function
-		{ $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
+		{ $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
 	| ptrref_operator cfa_identifier_parameter_declarator_tuple
-		{ $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
+		{ $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
 	| type_qualifier_list ptrref_operator cfa_identifier_parameter_declarator_tuple
-		{ $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
+		{ $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
 	;
 
@@ -2963,15 +2963,15 @@
 cfa_abstract_ptr:										// CFA
 	ptrref_operator type_specifier
-		{ $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
+		{ $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
 	| type_qualifier_list ptrref_operator type_specifier
-		{ $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
+		{ $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
 	| ptrref_operator cfa_abstract_function
-		{ $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
+		{ $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
 	| type_qualifier_list ptrref_operator cfa_abstract_function
-		{ $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
+		{ $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
 	| ptrref_operator cfa_abstract_declarator_tuple
-		{ $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
+		{ $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
 	| type_qualifier_list ptrref_operator cfa_abstract_declarator_tuple
-		{ $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
+		{ $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
 	;
 
Index: src/ResolvExpr/Unify.cc
===================================================================
--- src/ResolvExpr/Unify.cc	(revision f7cb0bc76af10982d6f4f34f060acc53a8dc27f9)
+++ src/ResolvExpr/Unify.cc	(revision b1e63ac54a1b3b3705d130858c9772e8b84c867f)
@@ -42,4 +42,5 @@
 		virtual void visit(PointerType *pointerType);
 		virtual void visit(ArrayType *arrayType);
+		virtual void visit(ReferenceType *refType);
 		virtual void visit(FunctionType *functionType);
 		virtual void visit(StructInstType *aggregateUseType);
@@ -428,4 +429,12 @@
 	}
 
+	void Unify::visit(ReferenceType *refType) {
+		if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {
+			result = unifyExact( refType->get_base(), otherRef->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
+			markAssertions( haveAssertions, needAssertions, refType );
+			markAssertions( haveAssertions, needAssertions, otherRef );
+		} // if
+	}
+
 	void Unify::visit(ArrayType *arrayType) {
 		ArrayType *otherArray = dynamic_cast< ArrayType* >( type2 );
Index: src/SymTab/Autogen.cc
===================================================================
--- src/SymTab/Autogen.cc	(revision f7cb0bc76af10982d6f4f34f060acc53a8dc27f9)
+++ src/SymTab/Autogen.cc	(revision b1e63ac54a1b3b3705d130858c9772e8b84c867f)
@@ -176,5 +176,6 @@
 			FunctionType * ftype = funcDecl->get_functionType();
 			assert( ! ftype->get_parameters().empty() );
-			Type * t = safe_dynamic_cast< PointerType * >( ftype->get_parameters().front()->get_type() )->get_base();
+			Type * t = InitTweak::getPointerBase( ftype->get_parameters().front()->get_type() );
+			assert( t );
 			map.insert( Mangler::mangleType( t ), true );
 		}
Index: src/SymTab/Indexer.cc
===================================================================
--- src/SymTab/Indexer.cc	(revision f7cb0bc76af10982d6f4f34f060acc53a8dc27f9)
+++ src/SymTab/Indexer.cc	(revision b1e63ac54a1b3b3705d130858c9772e8b84c867f)
@@ -158,5 +158,6 @@
 				assert( ! params.empty() );
 				// use base type of pointer, so that qualifiers on the pointer type aren't considered.
-				Type * base = safe_dynamic_cast< PointerType * >( params.front()->get_type() )->get_base();
+				Type * base = InitTweak::getPointerBase( params.front()->get_type() );
+				assert( base );
 				funcMap[ Mangler::mangle( base ) ] += function;
 			} else {
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision f7cb0bc76af10982d6f4f34f060acc53a8dc27f9)
+++ src/SymTab/Validate.cc	(revision b1e63ac54a1b3b3705d130858c9772e8b84c867f)
@@ -824,5 +824,6 @@
 			}
 			PointerType * ptrType = dynamic_cast< PointerType * >( params.front()->get_type() );
-			if ( ! ptrType || ptrType->is_array() ) {
+			ReferenceType * refType = dynamic_cast< ReferenceType * >( params.front()->get_type() );
+			if ( ( ! ptrType && ! refType ) || ( ptrType && ptrType->is_array() ) ) {
 				throw SemanticError( "First parameter of a constructor, destructor, or assignment function must be a pointer ", funcDecl );
 			}
Index: src/SynTree/AddressExpr.cc
===================================================================
--- src/SynTree/AddressExpr.cc	(revision f7cb0bc76af10982d6f4f34f060acc53a8dc27f9)
+++ src/SynTree/AddressExpr.cc	(revision b1e63ac54a1b3b3705d130858c9772e8b84c867f)
@@ -20,5 +20,10 @@
 AddressExpr::AddressExpr( Expression *arg, Expression *_aname ) : Expression( _aname ), arg( arg ) {
 	if ( arg->has_result() ) {
-		set_result( new PointerType( Type::Qualifiers(), arg->get_result()->clone() ) );
+		if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( arg->get_result() ) ) {
+			// xxx - very temporary, make &ref look like **
+			set_result( new PointerType( Type::Qualifiers( Type::Lvalue ), refType->get_base()->clone() ) );
+		} else {
+			set_result( new PointerType( Type::Qualifiers(), arg->get_result()->clone() ) );
+		}
 	}
 }
Index: src/SynTree/Mutator.cc
===================================================================
--- src/SynTree/Mutator.cc	(revision f7cb0bc76af10982d6f4f34f060acc53a8dc27f9)
+++ src/SynTree/Mutator.cc	(revision b1e63ac54a1b3b3705d130858c9772e8b84c867f)
@@ -473,4 +473,10 @@
 }
 
+Type *Mutator::mutate( ReferenceType *refType ) {
+	mutateAll( refType->get_forall(), *this );
+	refType->set_base( maybeMutate( refType->get_base(), *this ) );
+	return refType;
+}
+
 Type *Mutator::mutate( FunctionType *functionType ) {
 	mutateAll( functionType->get_forall(), *this );
Index: src/SynTree/Mutator.h
===================================================================
--- src/SynTree/Mutator.h	(revision f7cb0bc76af10982d6f4f34f060acc53a8dc27f9)
+++ src/SynTree/Mutator.h	(revision b1e63ac54a1b3b3705d130858c9772e8b84c867f)
@@ -92,4 +92,5 @@
 	virtual Type* mutate( PointerType *pointerType );
 	virtual Type* mutate( ArrayType *arrayType );
+	virtual Type* mutate( ReferenceType *refType );
 	virtual Type* mutate( FunctionType *functionType );
 	virtual Type* mutate( StructInstType *aggregateUseType );
Index: src/SynTree/ReferenceType.cc
===================================================================
--- src/SynTree/ReferenceType.cc	(revision b1e63ac54a1b3b3705d130858c9772e8b84c867f)
+++ src/SynTree/ReferenceType.cc	(revision b1e63ac54a1b3b3705d130858c9772e8b84c867f)
@@ -0,0 +1,44 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// PointerType.cc --
+//
+// Author           : Rob Schluntz
+// Created On       : Fri May 12 18:12:15 2017
+// Last Modified By : Rob Schluntz
+// Last Modified On : Fri May 12 18:12:15 2017
+// Update Count     : 1
+//
+
+#include "Type.h"
+#include "Expression.h"
+#include "Common/utility.h"
+
+ReferenceType::ReferenceType( const Type::Qualifiers &tq, Type *base, const std::list< Attribute * > & attributes )
+  : Type( tq, attributes ), base( base ) {
+}
+
+ReferenceType::ReferenceType( const ReferenceType &other )
+  : Type( other ), base( maybeClone( other.base ) ) {
+}
+
+ReferenceType::~ReferenceType() {
+  delete base;
+}
+
+void ReferenceType::print( std::ostream &os, int indent ) const {
+  Type::print( os, indent );
+  os << "reference to ";
+  if ( base ) {
+    base->print( os, indent );
+  } // if
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/SynTree/SynTree.h
===================================================================
--- src/SynTree/SynTree.h	(revision f7cb0bc76af10982d6f4f34f060acc53a8dc27f9)
+++ src/SynTree/SynTree.h	(revision b1e63ac54a1b3b3705d130858c9772e8b84c867f)
@@ -101,4 +101,5 @@
 class PointerType;
 class ArrayType;
+class ReferenceType;
 class FunctionType;
 class ReferenceToType;
Index: src/SynTree/Type.h
===================================================================
--- src/SynTree/Type.h	(revision f7cb0bc76af10982d6f4f34f060acc53a8dc27f9)
+++ src/SynTree/Type.h	(revision b1e63ac54a1b3b3705d130858c9772e8b84c867f)
@@ -249,4 +249,6 @@
 	bool is_array() const { return isStatic || isVarLen || dimension; }
 
+	virtual bool isComplete() const { return ! isVarLen; }
+
 	virtual PointerType *clone() const { return new PointerType( *this ); }
 	virtual void accept( Visitor & v ) { v.visit( this ); }
@@ -290,4 +292,21 @@
 };
 
+class ReferenceType : public Type {
+public:
+	ReferenceType( const Type::Qualifiers & tq, Type *base, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
+	ReferenceType( const ReferenceType & );
+	virtual ~ReferenceType();
+
+	Type *get_base() { return base; }
+	void set_base( Type *newValue ) { base = newValue; }
+
+	virtual ReferenceType *clone() const { return new ReferenceType( *this ); }
+	virtual void accept( Visitor & v ) { v.visit( this ); }
+	virtual Type *acceptMutator( Mutator & m ) { return m.mutate( this ); }
+	virtual void print( std::ostream & os, int indent = 0 ) const;
+private:
+	Type *base;
+};
+
 class FunctionType : public Type {
   public:
Index: src/SynTree/Visitor.cc
===================================================================
--- src/SynTree/Visitor.cc	(revision f7cb0bc76af10982d6f4f34f060acc53a8dc27f9)
+++ src/SynTree/Visitor.cc	(revision b1e63ac54a1b3b3705d130858c9772e8b84c867f)
@@ -363,4 +363,5 @@
 void Visitor::visit( PointerType *pointerType ) {
 	acceptAll( pointerType->get_forall(), *this );
+	// xxx - should PointerType visit/mutate dimension?
 	maybeAccept( pointerType->get_base(), *this );
 }
@@ -370,4 +371,9 @@
 	maybeAccept( arrayType->get_dimension(), *this );
 	maybeAccept( arrayType->get_base(), *this );
+}
+
+void Visitor::visit( ReferenceType *refType ) {
+	acceptAll( refType->get_forall(), *this );
+	maybeAccept( refType->get_base(), *this );
 }
 
Index: src/SynTree/Visitor.h
===================================================================
--- src/SynTree/Visitor.h	(revision f7cb0bc76af10982d6f4f34f060acc53a8dc27f9)
+++ src/SynTree/Visitor.h	(revision b1e63ac54a1b3b3705d130858c9772e8b84c867f)
@@ -95,4 +95,5 @@
 	virtual void visit( PointerType *pointerType );
 	virtual void visit( ArrayType *arrayType );
+	virtual void visit( ReferenceType *refType );
 	virtual void visit( FunctionType *functionType );
 	virtual void visit( StructInstType *aggregateUseType );
Index: src/SynTree/module.mk
===================================================================
--- src/SynTree/module.mk	(revision f7cb0bc76af10982d6f4f34f060acc53a8dc27f9)
+++ src/SynTree/module.mk	(revision b1e63ac54a1b3b3705d130858c9772e8b84c867f)
@@ -20,4 +20,5 @@
        SynTree/PointerType.cc \
        SynTree/ArrayType.cc \
+       SynTree/ReferenceType.cc \
        SynTree/FunctionType.cc \
        SynTree/ReferenceToType.cc \
