Index: src/SynTree/ArrayType.cc
===================================================================
--- src/SynTree/ArrayType.cc	(revision 64ac636b5de5a469279d560f5378e5e32e271eec)
+++ src/SynTree/ArrayType.cc	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Feb  1 17:16:29 2017
-// Update Count     : 12
+// Last Modified On : Fri Mar 17 09:40:30 2017
+// Update Count     : 13
 //
 
@@ -21,5 +21,5 @@
 ArrayType::ArrayType( const Type::Qualifiers &tq, Type *base, Expression *dimension, bool isVarLen, bool isStatic, const std::list< Attribute * > & attributes )
 	: Type( tq, attributes ), base( base ), dimension( dimension ), isVarLen( isVarLen ), isStatic( isStatic ) {
-	base->set_isLvalue( false );
+	base->set_lvalue( false );
 }
 
Index: src/SynTree/Expression.cc
===================================================================
--- src/SynTree/Expression.cc	(revision 64ac636b5de5a469279d560f5378e5e32e271eec)
+++ src/SynTree/Expression.cc	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Aug  5 14:23:56 2016
-// Update Count     : 49
+// Last Modified On : Fri Mar 17 09:42:04 2017
+// Update Count     : 51
 //
 
@@ -77,5 +77,5 @@
 	assert( var->get_type() );
 	Type * type = var->get_type()->clone();
-	type->set_isLvalue( true );
+	type->set_lvalue( true );
 	set_result( type );
 }
@@ -352,5 +352,5 @@
 	sub.apply( res );
 	set_result( res );
-	get_result()->set_isLvalue( true );
+	get_result()->set_lvalue( true );
 }
 
Index: src/SynTree/TupleExpr.cc
===================================================================
--- src/SynTree/TupleExpr.cc	(revision 64ac636b5de5a469279d560f5378e5e32e271eec)
+++ src/SynTree/TupleExpr.cc	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Mon May 18 10:59:19 2015
-// Update Count     : 1
+// Last Modified On : Fri Mar 17 09:42:29 2017
+// Update Count     : 3
 //
 
@@ -60,5 +60,5 @@
 	assertf( type->size() > index, "TupleIndexExpr index out of bounds: tuple size %d, requested index %d in expr %s", type->size(), index, toString( tuple ).c_str() );
 	set_result( (*std::next( type->get_types().begin(), index ))->clone() );
-	get_result()->set_isLvalue( type->get_isLvalue() );
+	get_result()->set_lvalue( type->get_lvalue() );
 }
 
Index: src/SynTree/Type.cc
===================================================================
--- src/SynTree/Type.cc	(revision 64ac636b5de5a469279d560f5378e5e32e271eec)
+++ src/SynTree/Type.cc	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Mar 16 10:25:06 2017
-// Update Count     : 23
+// Last Modified On : Fri Mar 17 08:42:47 2017
+// Update Count     : 28
 //
 
@@ -19,4 +19,5 @@
 #include "Declaration.h"
 #include "Attribute.h"
+#include "InitTweak/InitTweak.h"
 #include "Common/utility.h"
 
@@ -60,7 +61,15 @@
 
 // These must remain in the same order as the corresponding bit fields.
-const char * Type::FuncSpecifiers::Names[] = { "inline", "fortran", "_Noreturn" };
-const char * Type::StorageClasses::Names[] = { "extern", "static", "auto", "register", "_Thread_local" };
-const char * Type::Qualifiers::Names[] = { "const", "restrict", "volatile", "lvalue", "mutex", "_Atomic" };
+const char * Type::FuncSpecifiersNames[] = { "inline", "fortran", "_Noreturn" };
+const char * Type::StorageClassesNames[] = { "extern", "static", "auto", "register", "_Thread_local" };
+const char * Type::QualifiersNames[] = { "const", "restrict", "volatile", "lvalue", "mutex", "_Atomic" };
+
+Type *Type::stripDeclarator() {
+	Type * type = this;
+	while ( Type * at = InitTweak::getPointerBase( type ) ) {
+		type = at;
+	}
+	return type;
+}
 
 void Type::print( std::ostream &os, int indent ) const {
Index: src/SynTree/Type.h
===================================================================
--- src/SynTree/Type.h	(revision 64ac636b5de5a469279d560f5378e5e32e271eec)
+++ src/SynTree/Type.h	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Mar 16 12:11:50 2017
-// Update Count     : 116
+// Last Modified On : Fri Mar 17 09:04:03 2017
+// Update Count     : 147
 //
 
@@ -21,16 +21,40 @@
 #include "SynTree.h"
 #include "Visitor.h"
+#include <strings.h>									// ffs
 
 class Type : public BaseSyntaxNode {
   public:
-	#define CommonBF( N ) \
+	// Simulate inheritance because union does not allow it.
+	// Bug in g++-4.9 prevents static field in union
+	//static const char * Names[];
+	#define BFCommon( BFType, N ) \
 		bool operator[]( unsigned int i ) const { return val & (1 << i); } \
 		bool any() const { return val != 0; } \
-		static const char * Names[]; \
+		void reset() { val = 0; } \
+		int ffs() { return ::ffs( val ) - 1; } \
+		BFType operator&=( BFType other ) { \
+			val &= other.val; return *this; \
+		} \
+	 	BFType operator&( BFType other ) const { \
+			BFType q = other; \
+			q &= *this; \
+			return q; \
+		} \
+	 	BFType operator|=( BFType other ) { \
+			val |= other.val; return *this; \
+		} \
+	 	BFType operator|( BFType other ) const { \
+			BFType q = other; \
+			q |= *this; \
+			return q; \
+		} \
+	 	BFType operator-=( BFType other ) { \
+			val &= ~other.val; return *this; \
+		} \
 		void print( std::ostream & os ) const { \
 			if ( (*this).any() ) { \
 				for ( unsigned int i = 0; i < N; i += 1 ) { \
 					if ( (*this)[i] ) { \
-						os << Names[i] << ' '; \
+						os << BFType##Names[i] << ' '; \
 					} \
 				} \
@@ -41,4 +65,5 @@
 
 	enum { Inline = 1 << 0, Noreturn = 1 << 1, Fortran = 1 << 2, NumFuncSpecifier = 3 };
+	static const char * FuncSpecifiersNames[];
 	union FuncSpecifiers {
 		unsigned int val;
@@ -50,8 +75,10 @@
 		FuncSpecifiers() : val( 0 ) {}
 		FuncSpecifiers( unsigned int val ) : val( val ) {}
-		CommonBF( NumFuncSpecifier )
+		// equality (==, !=) works implicitly on first field "val", relational operations are undefined.
+		BFCommon( FuncSpecifiers, NumFuncSpecifier )
 	}; // FuncSpecifiers
 
 	enum { Extern = 1 << 0, Static = 1 << 1, Auto = 1 << 2, Register = 1 << 3, Threadlocal = 1 << 4, NumStorageClass = 5 };
+	static const char * StorageClassesNames[];
 	union StorageClasses {
 		unsigned int val;
@@ -66,57 +93,35 @@
 		StorageClasses() : val( 0 ) {}
 		StorageClasses( unsigned int val ) : val( val ) {}
-		CommonBF( NumStorageClass )
+		// equality (==, !=) works implicitly on first field "val", relational operations are undefined.
+		BFCommon( StorageClasses, NumStorageClass )
 	}; // StorageClasses
 
 	enum { Const = 1 << 0, Restrict = 1 << 1, Volatile = 1 << 2, Lvalue = 1 << 3, Mutex = 1 << 4, Atomic = 1 << 5, NumTypeQualifier = 6 };
+	static const char * QualifiersNames[];
 	union Qualifiers {
 		enum { Mask = ~(Restrict | Lvalue) };
 		unsigned int val;
 		struct {
-			bool isConst : 1;
-			bool isRestrict : 1;
-			bool isVolatile : 1;
-			bool isLvalue : 1;
-			bool isMutex : 1;
-			bool isAtomic : 1;
+			bool is_const : 1;
+			bool is_restrict : 1;
+			bool is_volatile : 1;
+			bool is_lvalue : 1;
+			bool is_mutex : 1;
+			bool is_atomic : 1;
 		};
 
 		Qualifiers() : val( 0 ) {}
 		Qualifiers( unsigned int val ) : val( val ) {}
-		bool operator==( Qualifiers other ) const {
-			return (val & Mask) == (other.val & Mask);
+		// Complex comparisons provide implicit qualifier downcasting, e.g., T downcast to const T.
+		bool operator==( Qualifiers other ) const { return (val & Mask) == (other.val & Mask); }
+		bool operator!=( Qualifiers other ) const { return (val & Mask) != (other.val & Mask); }
+		bool operator<=( Qualifiers other ) const {
+			return is_const <= other.is_const && is_volatile <= other.is_volatile &&
+				is_mutex >= other.is_mutex && is_atomic == other.is_atomic;
 		}
-		bool operator!=( Qualifiers other ) const {
-			return (val & Mask) != (other.val & Mask);
-		}
-		bool operator<=( Qualifiers other ) const {
-			return isConst <= other.isConst && isVolatile <= other.isVolatile &&
-				isMutex == other.isMutex && isAtomic == other.isAtomic;
-		}
-	 	bool operator>=( Qualifiers other ) const {
-			return isConst >= other.isConst	&& isVolatile >= other.isVolatile &&
-				isMutex == other.isMutex && isAtomic == other.isAtomic;
-		}
-		bool operator<( Qualifiers other ) const {
-			return *this != other && *this <= other;
-		}
-	 	bool operator>( Qualifiers other ) const {
-			return *this != other && *this >= other;
-		}
-		Qualifiers operator&=( Type::Qualifiers other ) {
-			val &= other.val; return *this;
-		}
-	 	Qualifiers operator+=( Qualifiers other ) {
-			val |= other.val; return *this;
-		}
-	 	Qualifiers operator-=( Qualifiers other ) {
-			val &= ~other.val; return *this;
-		}
-	 	Qualifiers operator+( Qualifiers other ) const {
-			Qualifiers q = other;
-			q += *this;
-			return q;
-		}
-		CommonBF( NumTypeQualifier )
+		bool operator<( Qualifiers other ) const { return *this != other && *this <= other; }
+	 	bool operator>=( Qualifiers other ) const { return ! (*this < other); }
+	 	bool operator>( Qualifiers other ) const { return *this != other && *this >= other; }
+		BFCommon( Qualifiers, NumTypeQualifier )
 	}; // Qualifiers
 
@@ -126,14 +131,16 @@
 
 	Qualifiers & get_qualifiers() { return tq; }
-	bool get_isConst() { return tq.isConst; }
-	bool get_isVolatile() { return tq.isVolatile; }
-	bool get_isRestrict() { return tq.isRestrict; }
-	bool get_isLvalue() { return tq.isLvalue; }
-	bool get_isAtomic() { return tq.isAtomic; }
-	void set_isConst( bool newValue ) { tq.isConst = newValue; }
-	void set_isVolatile( bool newValue ) { tq.isVolatile = newValue; }
-	void set_isRestrict( bool newValue ) { tq.isRestrict = newValue; }
-	void set_isLvalue( bool newValue ) { tq.isLvalue = newValue; }
-	void set_isAtomic( bool newValue ) { tq.isAtomic = newValue; }
+	bool get_const() { return tq.is_const; }
+	bool get_volatile() { return tq.is_volatile; }
+	bool get_restrict() { return tq.is_restrict; }
+	bool get_lvalue() { return tq.is_lvalue; }
+	bool get_mutex() { return tq.is_mutex; }
+	bool get_atomic() { return tq.is_atomic; }
+	void set_const( bool newValue ) { tq.is_const = newValue; }
+	void set_volatile( bool newValue ) { tq.is_volatile = newValue; }
+	void set_restrict( bool newValue ) { tq.is_restrict = newValue; }
+	void set_lvalue( bool newValue ) { tq.is_lvalue = newValue; }
+	void set_mutex( bool newValue ) { tq.is_mutex = newValue; }
+	void set_atomic( bool newValue ) { tq.is_atomic = newValue; }
 
 	typedef std::list<TypeDecl *> ForallList;
@@ -147,4 +154,6 @@
 	virtual bool isVoid() const { return size() == 0; }
 	virtual Type * getComponent( unsigned i ) { assertf( size() == 1 && i == 0, "Type::getComponent was called with size %d and index %d\n", size(), i ); return this; }
+
+	Type *stripDeclarator();
 
 	virtual bool isComplete() const { return true; }
Index: src/SynTree/TypeSubstitution.cc
===================================================================
--- src/SynTree/TypeSubstitution.cc	(revision 64ac636b5de5a469279d560f5378e5e32e271eec)
+++ src/SynTree/TypeSubstitution.cc	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -9,7 +9,7 @@
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Rob Schluntz
-// Last Modified On : Tue Apr 26 11:15:29 2016
-// Update Count     : 3
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Thu Mar 16 15:54:35 2017
+// Update Count     : 4
 //
 
@@ -127,5 +127,5 @@
 		subCount++;
 		Type *newtype = i->second->clone();
-		newtype->get_qualifiers() += inst->get_qualifiers();
+		newtype->get_qualifiers() |= inst->get_qualifiers();
 		delete inst;
 		return newtype;
