Index: src/ResolvExpr/CommonType.cc
===================================================================
--- src/ResolvExpr/CommonType.cc	(revision d7dc82447d825854b37e78a7aa777b1a58e7e1b2)
+++ src/ResolvExpr/CommonType.cc	(revision 6b9b04774733cb2fbec40e4c126e7097d99a9290)
@@ -17,5 +17,4 @@
 #include "SynTree/Type.h"
 #include "Unify.h"
-
 
 /// #define DEBUG
@@ -31,4 +30,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 );
@@ -42,5 +42,6 @@
 		virtual void visit( OneType *oneType );
 
-		void getCommonWithVoidPointer( PointerType* voidPointer, PointerType* otherPointer );
+		template< typename Pointer > void getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer );
+		template< typename RefType > void handleRefType( RefType *inst, Type *other );
 
 		Type *result;
@@ -52,6 +53,43 @@
 	};
 
+	Type * handleReference( ReferenceType * refType, Type * other, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment & env, const OpenVarSet &openVars ) {
+		Type * result = nullptr, * common = nullptr;
+		AssertionSet have, need;
+		OpenVarSet newOpen( openVars );
+		// need unify to bind type variables
+		if ( unify( refType->get_base(), other, env, have, need, newOpen, indexer, common ) ) {
+			// std::cerr << "unify success" << std::endl;
+			if ( widenSecond ) {
+				if ( widenFirst || other->get_qualifiers() <= refType->get_qualifiers() ) {
+					result = new ReferenceType( refType->get_qualifiers(), common ); // refType->clone();
+					result->get_qualifiers() |= other->get_qualifiers();
+				}
+			} else if ( widenFirst ) {
+				if ( widenSecond || refType->get_qualifiers() <= other->get_qualifiers() ) {
+					result = common;
+					result->get_qualifiers() |= refType->get_qualifiers();
+				}
+			}
+		} else {
+			// std::cerr << "exact unify failed: " << refType << " " << other << std::endl;
+		}
+		// std::cerr << "common type of reference [" << refType << "] and non-reference [" << other << "] is [" << result << "]" << std::endl;
+		return result;
+	}
+
 	Type *commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) {
 		CommonType visitor( type2, widenFirst, widenSecond, indexer, env, openVars );
+
+		ReferenceType * refType1 = dynamic_cast< ReferenceType * >( type1 );
+		ReferenceType * refType2 = dynamic_cast< ReferenceType * >( type2 );
+		if ( (refType1 || refType2) && (! refType1 || ! refType2) ) {
+			// handle the case where exactly one of the types is a reference type specially
+			if ( refType1 ) {
+				return handleReference( refType1, type2, widenFirst, widenSecond, indexer, env, openVars );
+			} else if ( refType2 ) {
+				return handleReference( refType2, type1, widenSecond, widenFirst, indexer, env, openVars );
+			}
+		}
+
 		type1->accept( visitor );
 		Type *result = visitor.get_result();
@@ -142,5 +180,6 @@
 	}
 
-	void CommonType::getCommonWithVoidPointer( PointerType* voidPointer, PointerType* otherPointer ) {
+	template< typename Pointer >
+	void CommonType::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) {
 		if ( TypeInstType* var = dynamic_cast< TypeInstType* >( otherPointer->get_base() ) ) {
 			OpenVarSet::const_iterator entry = openVars.find( var->get_name() );
@@ -188,4 +227,37 @@
 
 	void CommonType::visit( __attribute((unused)) ArrayType *arrayType ) {}
+
+	void CommonType::visit( ReferenceType *refType ) {
+		if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {
+			if ( widenFirst && dynamic_cast< VoidType* >( otherRef->get_base() ) && ! isFtype(refType->get_base()) ) {
+				getCommonWithVoidPointer( otherRef, refType );
+			} else if ( widenSecond && dynamic_cast< VoidType* >( refType->get_base() ) && ! isFtype(otherRef->get_base()) ) {
+				getCommonWithVoidPointer( refType, otherRef );
+			} else if ( ( refType->get_base()->get_qualifiers() >= otherRef->get_base()->get_qualifiers() || widenFirst )
+					   && ( refType->get_base()->get_qualifiers() <= otherRef->get_base()->get_qualifiers() || widenSecond ) ) {
+				Type::Qualifiers tq1 = refType->get_base()->get_qualifiers(), tq2 = otherRef->get_base()->get_qualifiers();
+				refType->get_base()->get_qualifiers() = Type::Qualifiers();
+				otherRef->get_base()->get_qualifiers() = Type::Qualifiers();
+				AssertionSet have, need;
+				OpenVarSet newOpen( openVars );
+				if ( unifyExact( refType->get_base(), otherRef->get_base(), env, have, need, newOpen, indexer ) ) {
+					if ( tq1 < tq2 ) {
+						result = refType->clone();
+					} else {
+						result = otherRef->clone();
+					} // if
+					result->get_qualifiers() = tq1 | tq2;
+				} else {
+					/// std::cout << "place for ptr-to-type" << std::endl;
+				} // if
+				refType->get_base()->get_qualifiers() = tq1;
+				otherRef->get_base()->get_qualifiers() = tq2;
+			} // if
+		} else if ( widenSecond && dynamic_cast< ZeroType* >( type2 ) ) {
+			result = refType->clone();
+			result->get_qualifiers() |= type2->get_qualifiers();
+		} // if
+	}
+
 	void CommonType::visit( __attribute((unused)) FunctionType *functionType ) {}
 	void CommonType::visit( __attribute((unused)) StructInstType *aggregateUseType ) {}
@@ -195,8 +267,7 @@
 		if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType* >( type2 ) || dynamic_cast< OneType* >( type2 ) ) {
 			// reuse BasicType, EnumInstType code by swapping type2 with enumInstType
-			Type * temp = type2;
+			ValueGuard< Type * > temp( type2 );
 			type2 = enumInstType;
-			temp->accept( *this );
-			type2 = temp;
+			temp.old->accept( *this );
 		} // if
 	}
