Index: src/CodeGen/GenType.cc
===================================================================
--- src/CodeGen/GenType.cc	(revision 65aca88c360c68fb3e17eb3a984a3727a769f630)
+++ src/CodeGen/GenType.cc	(revision ce8c12fdff03df2cb8b704ff8bcc77c923e2b6e1)
@@ -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 65aca88c360c68fb3e17eb3a984a3727a769f630)
+++ src/Concurrency/Keywords.cc	(revision ce8c12fdff03df2cb8b704ff8bcc77c923e2b6e1)
@@ -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( StructDecl * decl, 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 65aca88c360c68fb3e17eb3a984a3727a769f630)
+++ src/GenPoly/Lvalue.cc	(revision ce8c12fdff03df2cb8b704ff8bcc77c923e2b6e1)
@@ -32,4 +32,5 @@
 #include "Common/UniqueName.h"
 #include "Common/utility.h"
+#include "InitTweak/InitTweak.h"
 
 namespace GenPoly {
@@ -40,6 +41,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 );
@@ -105,4 +110,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 );
 		}
 
@@ -165,4 +185,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 ) );
@@ -178,4 +208,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 65aca88c360c68fb3e17eb3a984a3727a769f630)
+++ src/InitTweak/FixInit.cc	(revision ce8c12fdff03df2cb8b704ff8bcc77c923e2b6e1)
@@ -400,5 +400,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 65aca88c360c68fb3e17eb3a984a3727a769f630)
+++ src/InitTweak/GenInit.cc	(revision ce8c12fdff03df2cb8b704ff8bcc77c923e2b6e1)
@@ -243,6 +243,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 65aca88c360c68fb3e17eb3a984a3727a769f630)
+++ src/InitTweak/InitTweak.cc	(revision ce8c12fdff03df2cb8b704ff8bcc77c923e2b6e1)
@@ -461,4 +461,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;
@@ -544,10 +546,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/Makefile.in
===================================================================
--- src/Makefile.in	(revision 65aca88c360c68fb3e17eb3a984a3727a769f630)
+++ src/Makefile.in	(revision ce8c12fdff03df2cb8b704ff8bcc77c923e2b6e1)
@@ -173,4 +173,5 @@
 	SynTree/driver_cfa_cpp-PointerType.$(OBJEXT) \
 	SynTree/driver_cfa_cpp-ArrayType.$(OBJEXT) \
+	SynTree/driver_cfa_cpp-ReferenceType.$(OBJEXT) \
 	SynTree/driver_cfa_cpp-FunctionType.$(OBJEXT) \
 	SynTree/driver_cfa_cpp-ReferenceToType.$(OBJEXT) \
@@ -419,7 +420,7 @@
 	SymTab/Autogen.cc SynTree/Type.cc SynTree/VoidType.cc \
 	SynTree/BasicType.cc SynTree/PointerType.cc \
-	SynTree/ArrayType.cc SynTree/FunctionType.cc \
-	SynTree/ReferenceToType.cc SynTree/TupleType.cc \
-	SynTree/TypeofType.cc SynTree/AttrType.cc \
+	SynTree/ArrayType.cc SynTree/ReferenceType.cc \
+	SynTree/FunctionType.cc SynTree/ReferenceToType.cc \
+	SynTree/TupleType.cc SynTree/TypeofType.cc SynTree/AttrType.cc \
 	SynTree/VarArgsType.cc SynTree/ZeroOneType.cc \
 	SynTree/Constant.cc SynTree/Expression.cc SynTree/TupleExpr.cc \
@@ -757,4 +758,6 @@
 SynTree/driver_cfa_cpp-ArrayType.$(OBJEXT): SynTree/$(am__dirstamp) \
 	SynTree/$(DEPDIR)/$(am__dirstamp)
+SynTree/driver_cfa_cpp-ReferenceType.$(OBJEXT):  \
+	SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
 SynTree/driver_cfa_cpp-FunctionType.$(OBJEXT):  \
 	SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
@@ -930,4 +933,5 @@
 	-rm -f SynTree/driver_cfa_cpp-PointerType.$(OBJEXT)
 	-rm -f SynTree/driver_cfa_cpp-ReferenceToType.$(OBJEXT)
+	-rm -f SynTree/driver_cfa_cpp-ReferenceType.$(OBJEXT)
 	-rm -f SynTree/driver_cfa_cpp-Statement.$(OBJEXT)
 	-rm -f SynTree/driver_cfa_cpp-TupleExpr.$(OBJEXT)
@@ -1042,4 +1046,5 @@
 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-PointerType.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceToType.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-Statement.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-TupleExpr.Po@am__quote@
@@ -2110,4 +2115,18 @@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-ArrayType.obj `if test -f 'SynTree/ArrayType.cc'; then $(CYGPATH_W) 'SynTree/ArrayType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/ArrayType.cc'; fi`
+
+SynTree/driver_cfa_cpp-ReferenceType.o: SynTree/ReferenceType.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-ReferenceType.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Tpo -c -o SynTree/driver_cfa_cpp-ReferenceType.o `test -f 'SynTree/ReferenceType.cc' || echo '$(srcdir)/'`SynTree/ReferenceType.cc
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='SynTree/ReferenceType.cc' object='SynTree/driver_cfa_cpp-ReferenceType.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-ReferenceType.o `test -f 'SynTree/ReferenceType.cc' || echo '$(srcdir)/'`SynTree/ReferenceType.cc
+
+SynTree/driver_cfa_cpp-ReferenceType.obj: SynTree/ReferenceType.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-ReferenceType.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Tpo -c -o SynTree/driver_cfa_cpp-ReferenceType.obj `if test -f 'SynTree/ReferenceType.cc'; then $(CYGPATH_W) 'SynTree/ReferenceType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/ReferenceType.cc'; fi`
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='SynTree/ReferenceType.cc' object='SynTree/driver_cfa_cpp-ReferenceType.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-ReferenceType.obj `if test -f 'SynTree/ReferenceType.cc'; then $(CYGPATH_W) 'SynTree/ReferenceType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/ReferenceType.cc'; fi`
 
 SynTree/driver_cfa_cpp-FunctionType.o: SynTree/FunctionType.cc
Index: src/Parser/DeclarationNode.cc
===================================================================
--- src/Parser/DeclarationNode.cc	(revision 65aca88c360c68fb3e17eb3a984a3727a769f630)
+++ src/Parser/DeclarationNode.cc	(revision ce8c12fdff03df2cb8b704ff8bcc77c923e2b6e1)
@@ -326,7 +326,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 );
@@ -745,5 +745,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 65aca88c360c68fb3e17eb3a984a3727a769f630)
+++ src/Parser/ParseNode.h	(revision ce8c12fdff03df2cb8b704ff8bcc77c923e2b6e1)
@@ -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 65aca88c360c68fb3e17eb3a984a3727a769f630)
+++ src/Parser/TypeData.cc	(revision ce8c12fdff03df2cb8b704ff8bcc77c923e2b6e1)
@@ -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 ) {
Index: src/Parser/TypeData.h
===================================================================
--- src/Parser/TypeData.h	(revision 65aca88c360c68fb3e17eb3a984a3727a769f630)
+++ src/Parser/TypeData.h	(revision ce8c12fdff03df2cb8b704ff8bcc77c923e2b6e1)
@@ -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 );
Index: src/Parser/parser.yy
===================================================================
--- src/Parser/parser.yy	(revision 65aca88c360c68fb3e17eb3a984a3727a769f630)
+++ src/Parser/parser.yy	(revision ce8c12fdff03df2cb8b704ff8bcc77c923e2b6e1)
@@ -2377,7 +2377,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
@@ -2425,7 +2425,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; }
@@ -2465,7 +2465,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; }
@@ -2509,7 +2509,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 ); }
@@ -2553,7 +2553,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 ); }
@@ -2613,7 +2613,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 ); }
@@ -2656,11 +2656,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 ); }
@@ -2745,11 +2745,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 ); }
@@ -2824,11 +2824,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 ); }
@@ -2870,15 +2870,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 ) ); }
 	;
 
@@ -2958,15 +2958,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 65aca88c360c68fb3e17eb3a984a3727a769f630)
+++ src/ResolvExpr/Unify.cc	(revision ce8c12fdff03df2cb8b704ff8bcc77c923e2b6e1)
@@ -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 );
@@ -595,5 +604,5 @@
 			TypeExpr *otherParam = dynamic_cast< TypeExpr* >(*jt);
 			assertf(otherParam, "Aggregate parameters should be type expressions");
-			
+
 			Type* paramTy = param->get_type();
 			Type* otherParamTy = otherParam->get_type();
Index: src/SymTab/Autogen.cc
===================================================================
--- src/SymTab/Autogen.cc	(revision 65aca88c360c68fb3e17eb3a984a3727a769f630)
+++ src/SymTab/Autogen.cc	(revision ce8c12fdff03df2cb8b704ff8bcc77c923e2b6e1)
@@ -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 65aca88c360c68fb3e17eb3a984a3727a769f630)
+++ src/SymTab/Indexer.cc	(revision ce8c12fdff03df2cb8b704ff8bcc77c923e2b6e1)
@@ -156,5 +156,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 65aca88c360c68fb3e17eb3a984a3727a769f630)
+++ src/SymTab/Validate.cc	(revision ce8c12fdff03df2cb8b704ff8bcc77c923e2b6e1)
@@ -818,5 +818,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 65aca88c360c68fb3e17eb3a984a3727a769f630)
+++ src/SynTree/AddressExpr.cc	(revision ce8c12fdff03df2cb8b704ff8bcc77c923e2b6e1)
@@ -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 65aca88c360c68fb3e17eb3a984a3727a769f630)
+++ src/SynTree/Mutator.cc	(revision ce8c12fdff03df2cb8b704ff8bcc77c923e2b6e1)
@@ -462,4 +462,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 65aca88c360c68fb3e17eb3a984a3727a769f630)
+++ src/SynTree/Mutator.h	(revision ce8c12fdff03df2cb8b704ff8bcc77c923e2b6e1)
@@ -91,4 +91,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 ce8c12fdff03df2cb8b704ff8bcc77c923e2b6e1)
+++ src/SynTree/ReferenceType.cc	(revision ce8c12fdff03df2cb8b704ff8bcc77c923e2b6e1)
@@ -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 65aca88c360c68fb3e17eb3a984a3727a769f630)
+++ src/SynTree/SynTree.h	(revision ce8c12fdff03df2cb8b704ff8bcc77c923e2b6e1)
@@ -99,4 +99,5 @@
 class PointerType;
 class ArrayType;
+class ReferenceType;
 class FunctionType;
 class ReferenceToType;
Index: src/SynTree/Type.h
===================================================================
--- src/SynTree/Type.h	(revision 65aca88c360c68fb3e17eb3a984a3727a769f630)
+++ src/SynTree/Type.h	(revision ce8c12fdff03df2cb8b704ff8bcc77c923e2b6e1)
@@ -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,22 @@
 };
 
+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;
+	unsigned int level = 0;
+};
+
 class FunctionType : public Type {
   public:
Index: src/SynTree/Visitor.cc
===================================================================
--- src/SynTree/Visitor.cc	(revision 65aca88c360c68fb3e17eb3a984a3727a769f630)
+++ src/SynTree/Visitor.cc	(revision ce8c12fdff03df2cb8b704ff8bcc77c923e2b6e1)
@@ -354,4 +354,5 @@
 void Visitor::visit( PointerType *pointerType ) {
 	acceptAll( pointerType->get_forall(), *this );
+	// xxx - should PointerType visit/mutate dimension?
 	maybeAccept( pointerType->get_base(), *this );
 }
@@ -361,4 +362,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 65aca88c360c68fb3e17eb3a984a3727a769f630)
+++ src/SynTree/Visitor.h	(revision ce8c12fdff03df2cb8b704ff8bcc77c923e2b6e1)
@@ -94,4 +94,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 );
@@ -163,5 +164,5 @@
 			} // if
 		} catch( SemanticError &e ) {
-			e.set_location( (*i)->location );			
+			e.set_location( (*i)->location );
 			errors.append( e );
 		} // try
Index: src/SynTree/module.mk
===================================================================
--- src/SynTree/module.mk	(revision 65aca88c360c68fb3e17eb3a984a3727a769f630)
+++ src/SynTree/module.mk	(revision ce8c12fdff03df2cb8b704ff8bcc77c923e2b6e1)
@@ -20,4 +20,5 @@
        SynTree/PointerType.cc \
        SynTree/ArrayType.cc \
+       SynTree/ReferenceType.cc \
        SynTree/FunctionType.cc \
        SynTree/ReferenceToType.cc \
