Index: src/SynTree/AddressExpr.cc
===================================================================
--- src/SynTree/AddressExpr.cc	(revision 65cdc1ea35994157636feda1d881a0381d7a0fb5)
+++ src/SynTree/AddressExpr.cc	(revision 92360603d942184e66e5f92706ecc75c6b04f121)
@@ -18,7 +18,35 @@
 #include "Common/utility.h"
 
+// Address expressions are typed based on the following inference rules:
+//    E : lvalue T  &..& (n references)
+//   &E :        T *&..& (n references)
+//
+//    E : T  &..&        (m references)
+//   &E : T *&..&        (m-1 references)
+//
+// That is, lvalues becomes
+
+namespace {
+	Type * addrType( Type * type ) {
+		if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( type ) ) {
+			return new ReferenceType( refType->get_qualifiers(), addrType( refType->get_base() ) );
+		} else {
+			return new PointerType( Type::Qualifiers(), type->clone() );
+		}
+	}
+}
+
 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 ( arg->get_result()->get_lvalue() ) {
+			// lvalue, retains all layers of reference and gains a pointer inside the references
+			set_result( addrType( arg->get_result() ) );
+		} else {
+			// taking address of non-lvalue -- must be a reference, loses one layer of reference
+			ReferenceType * refType = safe_dynamic_cast< ReferenceType * >( arg->get_result() );
+			set_result( addrType( refType->get_base() ) );
+		}
+		// result of & is never an lvalue
+		get_result()->set_lvalue( false );
 	}
 }
Index: src/SynTree/ApplicationExpr.cc
===================================================================
--- src/SynTree/ApplicationExpr.cc	(revision 65cdc1ea35994157636feda1d881a0381d7a0fb5)
+++ src/SynTree/ApplicationExpr.cc	(revision 92360603d942184e66e5f92706ecc75c6b04f121)
@@ -44,5 +44,5 @@
 }
 
-ApplicationExpr::ApplicationExpr( Expression *funcExpr, const std::list< Expression * > & argList ) : function( funcExpr ), args( argList ) {
+ApplicationExpr::ApplicationExpr( Expression *funcExpr, const std::list<Expression *> & args ) : function( funcExpr ), args( args ) {
 	PointerType *pointer = safe_dynamic_cast< PointerType* >( funcExpr->get_result() );
 	FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() );
Index: src/SynTree/Expression.cc
===================================================================
--- src/SynTree/Expression.cc	(revision 65cdc1ea35994157636feda1d881a0381d7a0fb5)
+++ src/SynTree/Expression.cc	(revision 92360603d942184e66e5f92706ecc75c6b04f121)
@@ -34,4 +34,5 @@
 #include "InitTweak/InitTweak.h"
 
+#include "GenPoly/Lvalue.h"
 
 Expression::Expression( Expression *_aname ) : result( 0 ), env( 0 ), argName( _aname ) {}
@@ -92,4 +93,10 @@
 }
 
+VariableExpr * VariableExpr::functionPointer( FunctionDecl * func ) {
+	VariableExpr * funcExpr = new VariableExpr( func );
+	funcExpr->set_result( new PointerType( Type::Qualifiers(), funcExpr->get_result() ) );
+	return funcExpr;
+}
+
 void VariableExpr::print( std::ostream &os, int indent ) const {
 	os << "Variable Expression: ";
@@ -152,5 +159,5 @@
 
 void AlignofExpr::print( std::ostream &os, int indent) const {
-	os << std::string( indent, ' ' ) << "Alignof Expression on: ";
+	os << "Alignof Expression on: ";
 
 	if (isType)
@@ -261,5 +268,5 @@
 
 void AttrExpr::print( std::ostream &os, int indent) const {
-	os << std::string( indent, ' ' ) << "Attr ";
+	os << "Attr ";
 	attr->print( os, indent + 2 );
 	if ( isType || expr ) {
@@ -360,5 +367,7 @@
 namespace {
 	TypeSubstitution makeSub( Type * t ) {
-		if ( StructInstType * aggInst = dynamic_cast< StructInstType * >( t ) ) {
+		if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( t ) ) {
+			return makeSub( refType->get_base() );
+		} else if ( StructInstType * aggInst = dynamic_cast< StructInstType * >( t ) ) {
 			return TypeSubstitution( aggInst->get_baseParameters()->begin(), aggInst->get_baseParameters()->end(), aggInst->get_parameters().begin() );
 		} else if ( UnionInstType * aggInst = dynamic_cast< UnionInstType * >( t ) ) {
@@ -425,9 +434,13 @@
 	if ( Type * type = expr->get_result() ) {
 		Type * base = InitTweak::getPointerBase( type );
-		if ( ! base ) {
-			std::cerr << type << std::endl;
+		assertf( base, "expected pointer type in dereference (type was %s)", toString( type ).c_str() );
+		ret->set_result( base->clone() );
+		if ( GenPoly::referencesPermissable() ) {
+			// if references are still allowed in the AST, dereference returns a reference
+			ret->set_result( new ReferenceType( Type::Qualifiers(), ret->get_result() ) );
+		} else {
+			// references have been removed, in which case dereference returns an lvalue of the base type.
+			ret->get_result()->set_lvalue( true );
 		}
-		assertf( base, "expected pointer type in dereference\n" );
-		ret->set_result( maybeClone( base ) );
 	}
 	return ret;
@@ -493,5 +506,5 @@
 
 void LogicalExpr::print( std::ostream &os, int indent )const {
-	os << std::string( indent, ' ' ) << "Short-circuited operation (" << (isAnd?"and":"or") << ") on: ";
+	os << "Short-circuited operation (" << (isAnd?"and":"or") << ") on: ";
 	arg1->print(os);
 	os << " and ";
Index: src/SynTree/Expression.h
===================================================================
--- src/SynTree/Expression.h	(revision 65cdc1ea35994157636feda1d881a0381d7a0fb5)
+++ src/SynTree/Expression.h	(revision 92360603d942184e66e5f92706ecc75c6b04f121)
@@ -280,4 +280,6 @@
 	void set_var( DeclarationWithType * newValue ) { var = newValue; }
 
+	static VariableExpr * functionPointer( FunctionDecl * decl );
+
 	virtual VariableExpr * clone() const { return new VariableExpr( * this ); }
 	virtual void accept( Visitor & v ) { v.visit( this ); }
Index: src/SynTree/Mutator.cc
===================================================================
--- src/SynTree/Mutator.cc	(revision 65cdc1ea35994157636feda1d881a0381d7a0fb5)
+++ src/SynTree/Mutator.cc	(revision 92360603d942184e66e5f92706ecc75c6b04f121)
@@ -480,4 +480,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 65cdc1ea35994157636feda1d881a0381d7a0fb5)
+++ src/SynTree/Mutator.h	(revision 92360603d942184e66e5f92706ecc75c6b04f121)
@@ -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 92360603d942184e66e5f92706ecc75c6b04f121)
+++ src/SynTree/ReferenceType.cc	(revision 92360603d942184e66e5f92706ecc75c6b04f121)
@@ -0,0 +1,49 @@
+//
+// 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 ) {
+	assertf( base, "Reference Type with a null base created." );
+}
+
+ReferenceType::ReferenceType( const ReferenceType &other )
+	: Type( other ), base( maybeClone( other.base ) ) {
+}
+
+ReferenceType::~ReferenceType() {
+	delete base;
+}
+
+int ReferenceType::referenceDepth() const {
+	return base->referenceDepth()+1;
+}
+
+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 65cdc1ea35994157636feda1d881a0381d7a0fb5)
+++ src/SynTree/SynTree.h	(revision 92360603d942184e66e5f92706ecc75c6b04f121)
@@ -101,4 +101,5 @@
 class PointerType;
 class ArrayType;
+class ReferenceType;
 class FunctionType;
 class ReferenceToType;
Index: src/SynTree/Type.cc
===================================================================
--- src/SynTree/Type.cc	(revision 65cdc1ea35994157636feda1d881a0381d7a0fb5)
+++ src/SynTree/Type.cc	(revision 92360603d942184e66e5f92706ecc75c6b04f121)
@@ -65,5 +65,5 @@
 const char * Type::QualifiersNames[] = { "const", "restrict", "volatile", "lvalue", "mutex", "_Atomic" };
 
-Type *Type::stripDeclarator() {
+Type * Type::stripDeclarator() {
 	Type * type = this;
 	while ( Type * at = InitTweak::getPointerBase( type ) ) {
@@ -72,4 +72,14 @@
 	return type;
 }
+
+Type * Type::stripReferences() {
+	Type * type = this;
+	while ( ReferenceType * ref = dynamic_cast<ReferenceType *>( type ) ) {
+		type = ref->get_base();
+	}
+	return type;
+}
+
+int Type::referenceDepth() const { return 0; }
 
 void Type::print( std::ostream &os, int indent ) const {
Index: src/SynTree/Type.h
===================================================================
--- src/SynTree/Type.h	(revision 65cdc1ea35994157636feda1d881a0381d7a0fb5)
+++ src/SynTree/Type.h	(revision 92360603d942184e66e5f92706ecc75c6b04f121)
@@ -162,5 +162,11 @@
 
 	/// return type without outer pointers and arrays
-	Type *stripDeclarator();
+	Type * stripDeclarator();
+
+	/// return type without outer references
+	Type * stripReferences();
+
+	/// return the number of references occuring consecutively on the outermost layer of this type (i.e. do not count references nested within other types)
+	virtual int referenceDepth() const;
 
 	virtual bool isComplete() const { return true; }
@@ -256,4 +262,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 +298,23 @@
 };
 
+class ReferenceType : public Type {
+public:
+	Type *base;
+
+	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 int referenceDepth() const;
+
+	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;
+};
+
 class FunctionType : public Type {
   public:
Index: src/SynTree/TypeExpr.cc
===================================================================
--- src/SynTree/TypeExpr.cc	(revision 65cdc1ea35994157636feda1d881a0381d7a0fb5)
+++ src/SynTree/TypeExpr.cc	(revision 92360603d942184e66e5f92706ecc75c6b04f121)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// TypeExpr.cc -- 
+// TypeExpr.cc --
 //
 // Author           : Richard C. Bilson
Index: src/SynTree/Visitor.cc
===================================================================
--- src/SynTree/Visitor.cc	(revision 65cdc1ea35994157636feda1d881a0381d7a0fb5)
+++ src/SynTree/Visitor.cc	(revision 92360603d942184e66e5f92706ecc75c6b04f121)
@@ -368,4 +368,5 @@
 void Visitor::visit( PointerType *pointerType ) {
 	acceptAll( pointerType->get_forall(), *this );
+	// xxx - should PointerType visit/mutate dimension?
 	maybeAccept( pointerType->get_base(), *this );
 }
@@ -375,4 +376,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 65cdc1ea35994157636feda1d881a0381d7a0fb5)
+++ src/SynTree/Visitor.h	(revision 92360603d942184e66e5f92706ecc75c6b04f121)
@@ -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 65cdc1ea35994157636feda1d881a0381d7a0fb5)
+++ src/SynTree/module.mk	(revision 92360603d942184e66e5f92706ecc75c6b04f121)
@@ -20,4 +20,5 @@
        SynTree/PointerType.cc \
        SynTree/ArrayType.cc \
+       SynTree/ReferenceType.cc \
        SynTree/FunctionType.cc \
        SynTree/ReferenceToType.cc \
