Index: src/CodeGen/CodeGenerator.cc
===================================================================
--- src/CodeGen/CodeGenerator.cc	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/CodeGen/CodeGenerator.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 09:09:09 2017
-// Update Count     : 480
+// Last Modified On : Fri Mar 17 09:06:01 2017
+// Update Count     : 481
 //
 
@@ -539,5 +539,5 @@
 		if ( castExpr->get_result()->isVoid() ) {
 			output << "(void)" ;
-		} else if ( ! castExpr->get_result()->get_isLvalue() ) {
+		} else if ( ! castExpr->get_result()->get_lvalue() ) {
 			// at least one result type of cast, but not an lvalue
 			output << "(";
Index: src/CodeGen/GenType.cc
===================================================================
--- src/CodeGen/GenType.cc	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/CodeGen/GenType.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 Feb  2 13:53:43 2017
-// Update Count     : 20
+// Last Modified On : Fri Mar 17 09:02:28 2017
+// Update Count     : 22
 //
 
@@ -99,14 +99,14 @@
 			os << "static ";
 		} // if
-		if ( qualifiers.isConst ) {
+		if ( qualifiers.is_const ) {
 			os << "const ";
 		} // if
-		if ( qualifiers.isVolatile ) {
+		if ( qualifiers.is_volatile ) {
 			os << "volatile ";
 		} // if
-		if ( qualifiers.isRestrict ) {
+		if ( qualifiers.is_restrict ) {
 			os << "__restrict ";
 		} // if
-		if ( qualifiers.isAtomic ) {
+		if ( qualifiers.is_atomic ) {
 			os << "_Atomic ";
 		} // if
@@ -238,14 +238,14 @@
 
 	void GenType::handleQualifiers( Type *type ) {
-		if ( type->get_isConst() ) {
+		if ( type->get_const() ) {
 			typeString = "const " + typeString;
 		} // if
-		if ( type->get_isVolatile() ) {
+		if ( type->get_volatile() ) {
 			typeString = "volatile " + typeString;
 		} // if
-		if ( type->get_isRestrict() ) {
+		if ( type->get_restrict() ) {
 			typeString = "__restrict " + typeString;
 		} // if
-		if ( type->get_isAtomic() ) {
+		if ( type->get_atomic() ) {
 			typeString = "_Atomic " + typeString;
 		} // if
Index: src/Concurrency/Keywords.cc
===================================================================
--- src/Concurrency/Keywords.cc	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/Concurrency/Keywords.cc	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -12,5 +12,5 @@
 // Last Modified By :
 // Last Modified On :
-// Update Count     : 1
+// Update Count     : 3
 //
 
@@ -264,5 +264,5 @@
 			//Find mutex arguments
 			Type* ty = arg->get_type();
-			if( ! ty->get_qualifiers().isMutex ) continue;
+			if( ! ty->get_mutex() ) continue;
 
 			//Append it to the list
@@ -285,5 +285,5 @@
 
 		//Make sure that typed isn't mutex
-		if( base->get_qualifiers().isMutex ) throw SemanticError( "mutex keyword may only appear once per argument ", arg );
+		if( ! base->get_mutex() ) throw SemanticError( "mutex keyword may only appear once per argument ", arg );
 	}
 
Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/GenPoly/Box.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 08:35:33 2017
-// Update Count     : 338
+// Last Modified On : Fri Mar 17 09:06:37 2017
+// Update Count     : 339
 //
 
@@ -753,5 +753,5 @@
 					// if the argument's type is polymorphic, we don't need to box again!
 					return;
-				} else if ( arg->get_result()->get_isLvalue() ) {
+				} else if ( arg->get_result()->get_lvalue() ) {
 					// VariableExpr and MemberExpr are lvalues; need to check this isn't coming from the second arg of a comma expression though (not an lvalue)
 					// xxx - need to test that this code is still reachable
Index: src/GenPoly/Lvalue.cc
===================================================================
--- src/GenPoly/Lvalue.cc	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/GenPoly/Lvalue.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 : Tue Dec 15 15:33:13 2015
-// Update Count     : 3
+// Last Modified On : Fri Mar 17 09:11:18 2017
+// Update Count     : 5
 //
 
@@ -79,5 +79,5 @@
 			if ( function->get_returnVals().empty() ) return 0;
 			Type *ty = function->get_returnVals().front()->get_type();
-			return ty->get_isLvalue() ? ty : 0;
+			return ty->get_lvalue() ? ty : 0;
 		}
 
@@ -134,5 +134,5 @@
 		Statement * Pass1::mutate(ReturnStmt *retStmt) {
 			if ( retval && retStmt->get_expr() ) {
-				if ( retStmt->get_expr()->get_result()->get_isLvalue() ) {
+				if ( retStmt->get_expr()->get_result()->get_lvalue() ) {
 					// ***** Code Removal ***** because casts may be stripped already
 
Index: src/GenPoly/ScrubTyVars.cc
===================================================================
--- src/GenPoly/ScrubTyVars.cc	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/GenPoly/ScrubTyVars.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 : Tue May 19 16:42:42 2015
-// Update Count     : 2
+// Last Modified On : Thu Mar 16 15:44:27 2017
+// Update Count     : 3
 //
 
@@ -109,5 +109,5 @@
 		if ( Type *dynType = shouldScrub( pointer->get_base() ) ) {
 			Type *ret = dynType->acceptMutator( *this );
-			ret->get_qualifiers() += pointer->get_qualifiers();
+			ret->get_qualifiers() |= pointer->get_qualifiers();
 			pointer->set_base( 0 );
 			delete pointer;
Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/InitTweak/FixInit.cc	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -10,6 +10,6 @@
 // Created On       : Wed Jan 13 16:29:30 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Mar 16 08:08:04 2017
-// Update Count     : 67
+// Last Modified On : Fri Mar 17 09:13:47 2017
+// Update Count     : 71
 //
 
@@ -232,8 +232,9 @@
 			void handleFirstParam( Expression * firstParam );
 			template< typename... Params >
-			void emit( const Params &... params );
+			void emit( CodeLocation, const Params &... params );
 
 			FunctionDecl * function = 0;
-			std::set< DeclarationWithType * > unhandled, usedUninit;
+			std::set< DeclarationWithType * > unhandled;
+			std::map< DeclarationWithType *, CodeLocation > usedUninit;
 			ObjectDecl * thisParam = 0;
 			bool isCtor = false; // true if current function is a constructor
@@ -336,9 +337,4 @@
 			GenStructMemberCalls warner;
 			acceptAll( translationUnit, warner );
-
-			// visitor doesn't throw so that it can collect all errors
-			if ( ! warner.errors.isEmpty() ) {
-				throw warner.errors;
-			}
 		}
 
@@ -438,5 +434,5 @@
 			env->apply( result );
 			ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
-			tmp->get_type()->set_isConst( false );
+			tmp->get_type()->set_const( false );
 
 			// create and resolve copy constructor
@@ -484,8 +480,8 @@
 				env->apply( result );
 				ObjectDecl * ret = new ObjectDecl( retNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
-				ret->get_type()->set_isConst( false );
+				ret->get_type()->set_const( false );
 				impCpCtorExpr->get_returnDecls().push_back( ret );
 				CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
-				if ( ! result->get_isLvalue() ) {
+				if ( ! result->get_lvalue() ) {
 					// destructing lvalue returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary
 					destructRet( ret, impCpCtorExpr );
@@ -507,5 +503,5 @@
 				env->apply( result );
 				ObjectDecl * ret = new ObjectDecl( retNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
-				ret->get_type()->set_isConst( false );
+				ret->get_type()->set_const( false );
 				stmtExpr->get_returnDecls().push_front( ret );
 
@@ -588,5 +584,5 @@
 
 				Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) );
-				if ( callExpr->get_result()->get_isLvalue() ) {
+				if ( callExpr->get_result()->get_lvalue() ) {
 					// lvalue returning functions are funny. Lvalue.cc inserts a *? in front of any lvalue returning
 					// non-intrinsic function. Add an AddressExpr to the call to negate the derefence and change the
@@ -940,8 +936,9 @@
 			ValueGuard< FunctionDecl * > oldFunction( funcDecl );
 			ValueGuard< std::set< DeclarationWithType * > > oldUnhandled( unhandled );
-			ValueGuard< std::set< DeclarationWithType * > > oldUsedUninit( usedUninit );
+			ValueGuard< std::map< DeclarationWithType *, CodeLocation > > oldUsedUninit( usedUninit );
 			ValueGuard< ObjectDecl * > oldThisParam( thisParam );
 			ValueGuard< bool > oldIsCtor( isCtor );
 			ValueGuard< StructDecl * > oldStructDecl( structDecl );
+			errors = SemanticError();  // clear previous errors
 
 			// need to start with fresh sets
@@ -972,8 +969,18 @@
 			// remove the unhandled objects from usedUninit, because a call is inserted
 			// to handle them - only objects that are later constructed are used uninitialized.
-			std::set< DeclarationWithType * > diff;
-			std::set_difference( usedUninit.begin(), usedUninit.end(), unhandled.begin(), unhandled.end(), std::inserter( diff, diff.begin() ) );
-			for ( DeclarationWithType * member : diff ) {
-				emit( "in ", CodeGen::genPrettyType( function->get_functionType(), function->get_name() ), ", field ", member->get_name(), " used before being constructed" );
+			std::map< DeclarationWithType *, CodeLocation > diff;
+			// need the comparator since usedUninit and unhandled have different types
+			struct comp_t {
+				typedef decltype(usedUninit)::value_type usedUninit_t;
+				typedef decltype(unhandled)::value_type unhandled_t;
+				bool operator()(usedUninit_t x, unhandled_t y) { return x.first < y; }
+				bool operator()(unhandled_t x, usedUninit_t y) { return x < y.first; }
+			} comp;
+			std::set_difference( usedUninit.begin(), usedUninit.end(), unhandled.begin(), unhandled.end(), std::inserter( diff, diff.begin() ), comp );
+			for ( auto p : diff ) {
+				DeclarationWithType * member = p.first;
+				CodeLocation loc = p.second;
+				// xxx - make error message better by also tracking the location that the object is constructed at?
+				emit( loc, "in ", CodeGen::genPrettyType( function->get_functionType(), function->get_name() ), ", field ", member->get_name(), " used before being constructed" );
 			}
 
@@ -1020,9 +1027,12 @@
 							}
 						} catch ( SemanticError & error ) {
-							emit( "in ", CodeGen::genPrettyType( function->get_functionType(), function->get_name() ), ", field ", field->get_name(), " not explicitly ", isCtor ? "constructed" : "destructed",  " and no ", isCtor ? "default constructor" : "destructor", " found" );
+							emit( funcDecl->location, "in ", CodeGen::genPrettyType( function->get_functionType(), function->get_name() ), ", field ", field->get_name(), " not explicitly ", isCtor ? "constructed" : "destructed",  " and no ", isCtor ? "default constructor" : "destructor", " found" );
 						}
 					}
 				}
 				leaveScope();
+			}
+			if (! errors.isEmpty()) {
+				throw errors;
 			}
 		}
@@ -1079,5 +1089,5 @@
 							if ( unhandled.count( memberExpr->get_member() ) ) {
 								// emit a warning because a member was used before it was constructed
-								usedUninit.insert( memberExpr->get_member() );
+								usedUninit.insert( { memberExpr->get_member(), memberExpr->location } );
 							}
 						}
@@ -1089,13 +1099,15 @@
 
 		template< typename Visitor, typename... Params >
-		void error( Visitor & v, const Params &... params ) {
-			v.errors.append( toString( params... ) );
+		void error( Visitor & v, CodeLocation loc, const Params &... params ) {
+			SemanticError err( toString( params... ) );
+			err.set_location( loc );
+			v.errors.append( err );
 		}
 
 		template< typename... Params >
-		void GenStructMemberCalls::emit( const Params &... params ) {
+		void GenStructMemberCalls::emit( CodeLocation loc, const Params &... params ) {
 			// toggle warnings vs. errors here.
 			// warn( params... );
-			error( *this, params... );
+			error( *this, loc, params... );
 		}
 
Index: src/InitTweak/GenInit.cc
===================================================================
--- src/InitTweak/GenInit.cc	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/InitTweak/GenInit.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 08:01:25 2017
-// Update Count     : 181
+// Last Modified On : Fri Mar 17 09:12:36 2017
+// Update Count     : 183
 //
 
@@ -143,5 +143,5 @@
 		// is being returned
 		// Note: under the assumption that assignments return *this, checking for ?=? here is an optimization, since it shouldn't be necessary to copy construct `this`. This is a temporary optimization until reference types are added, at which point this should be removed, along with the analogous optimization in copy constructor generation.
-		if ( returnStmt->get_expr() && returnVals.size() == 1 && funcName != "?=?" && ! returnVals.front()->get_type()->get_isLvalue() ) {
+		if ( returnStmt->get_expr() && returnVals.size() == 1 && funcName != "?=?" && ! returnVals.front()->get_type()->get_lvalue() ) {
 			// explicitly construct the return value using the return expression and the retVal object
 			assertf( returnVals.front()->get_name() != "", "Function %s has unnamed return value\n", funcName.c_str() );
@@ -195,5 +195,5 @@
 
 			ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageClasses, LinkageSpec::C, 0, SymTab::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) );
-			arrayDimension->get_type()->set_isConst( true );
+			arrayDimension->get_type()->set_const( true );
 
 			arrayType->set_dimension( new VariableExpr( arrayDimension ) );
Index: src/Parser/DeclarationNode.cc
===================================================================
--- src/Parser/DeclarationNode.cc	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/Parser/DeclarationNode.cc	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -10,6 +10,6 @@
 // Created On       : Sat May 16 12:34:05 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Mar 16 09:10:57 2017
-// Update Count     : 1007
+// Last Modified On : Fri Mar 17 08:46:05 2017
+// Update Count     : 1017
 //
 
@@ -19,5 +19,4 @@
 #include <algorithm>
 #include <cassert>
-#include <strings.h>									// ffs
 
 #include "TypeData.h"
@@ -243,12 +242,9 @@
 
 DeclarationNode * DeclarationNode::newAggregate( Aggregate kind, const string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body ) {
+	assert( name );
 	DeclarationNode * newnode = new DeclarationNode;
 	newnode->type = new TypeData( TypeData::Aggregate );
 	newnode->type->aggregate.kind = kind;
-	if ( name ) {
-		newnode->type->aggregate.name = name;
-	} else {											// anonymous aggregate ?
-		newnode->type->aggregate.name = new string( anonymous.newName() );
-	} // if
+	newnode->type->aggregate.name = name;
 	newnode->type->aggregate.actuals = actuals;
 	newnode->type->aggregate.fields = fields;
@@ -258,11 +254,8 @@
 
 DeclarationNode * DeclarationNode::newEnum( string * name, DeclarationNode * constants, bool body ) {
+	assert( name );
 	DeclarationNode * newnode = new DeclarationNode;
 	newnode->type = new TypeData( TypeData::Enum );
-	if ( name ) {
-		newnode->type->enumeration.name = name;
-	} else {											// anonymous aggregate ?
-		newnode->type->enumeration.name = new string( anonymous.newName() );
-	} // if
+	newnode->type->enumeration.name = name;
 	newnode->type->enumeration.constants = constants;
 	newnode->type->enumeration.body = body;
@@ -436,8 +429,8 @@
 	const Type::Qualifiers qsrc = src->qualifiers, qdst = dst->qualifiers; // optimization
 
-	if ( (qsrc.val & qdst.val) != 0 ) {					// duplicates ?
+	if ( (qsrc & qdst).any() ) {						// duplicates ?
 		for ( unsigned int i = 0; i < Type::NumTypeQualifier; i += 1 ) { // find duplicates
 			if ( qsrc[i] && qdst[i] ) {
-				appendError( error, string( "duplicate " ) + Type::Qualifiers::Names[i] );
+				appendError( error, string( "duplicate " ) + Type::QualifiersNames[i] );
 			} // if
 		} // for
@@ -446,8 +439,8 @@
 
 void DeclarationNode::checkSpecifiers( DeclarationNode * src ) {
-	if ( (funcSpecs.val & src->funcSpecs.val) != 0 ) {	// duplicates ?
+	if ( (funcSpecs & src->funcSpecs).any() ) {			// duplicates ?
 		for ( unsigned int i = 0; i < Type::NumFuncSpecifier; i += 1 ) { // find duplicates
 			if ( funcSpecs[i] && src->funcSpecs[i] ) {
-				appendError( error, string( "duplicate " ) + Type::FuncSpecifiers::Names[i] );
+				appendError( error, string( "duplicate " ) + Type::FuncSpecifiersNames[i] );
 			} // if
 		} // for
@@ -455,15 +448,15 @@
 
 	if ( storageClasses.any() && src->storageClasses.any() ) { // any reason to check ?
-		if ( (storageClasses.val & src->storageClasses.val ) != 0 ) { // duplicates ?
+		if ( (storageClasses & src->storageClasses ).any() ) { // duplicates ?
 			for ( unsigned int i = 0; i < Type::NumStorageClass; i += 1 ) { // find duplicates
 				if ( storageClasses[i] && src->storageClasses[i] ) {
-					appendError( error, string( "duplicate " ) + Type::StorageClasses::Names[i] );
+					appendError( error, string( "duplicate " ) + Type::StorageClassesNames[i] );
 				} // if
 			} // for
 			// src is the new item being added and has a single bit
 		} else if ( ! src->storageClasses.is_threadlocal ) { // conflict ?
-			appendError( error, string( "conflicting " ) + Type::StorageClasses::Names[ffs( storageClasses.val ) - 1] +
-						 " & " + Type::StorageClasses::Names[ffs( src->storageClasses.val ) - 1] );
-			src->storageClasses.val = 0;				// FIX to preserve invariant of one basic storage specifier
+			appendError( error, string( "conflicting " ) + Type::StorageClassesNames[storageClasses.ffs()] +
+						 " & " + Type::StorageClassesNames[src->storageClasses.ffs()] );
+			src->storageClasses.reset();				// FIX to preserve invariant of one basic storage specifier
 		} // if
 	} // if
@@ -473,6 +466,6 @@
 
 DeclarationNode * DeclarationNode::copySpecifiers( DeclarationNode * q ) {
-	funcSpecs.val |= q->funcSpecs.val;
-	storageClasses.val |= q->storageClasses.val;
+	funcSpecs |= q->funcSpecs;
+	storageClasses |= q->storageClasses;
 
 	for ( Attribute *attr: reverseIterate( q->attributes ) ) {
@@ -497,5 +490,5 @@
 		src = nullptr;
 	} else {
-		dst->qualifiers += src->qualifiers;
+		dst->qualifiers |= src->qualifiers;
 	} // if
 } // addQualifiersToType
@@ -555,10 +548,10 @@
 		switch ( dst->kind ) {
 		  case TypeData::Unknown:
-			src->qualifiers += dst->qualifiers;
+			src->qualifiers |= dst->qualifiers;
 			dst = src;
 			src = nullptr;
 			break;
 		  case TypeData::Basic:
-			dst->qualifiers += src->qualifiers;
+			dst->qualifiers |= src->qualifiers;
 			if ( src->kind != TypeData::Unknown ) {
 				assert( src->kind == TypeData::Basic );
@@ -596,5 +589,5 @@
 					dst->base->aggInst.params = maybeClone( src->aggregate.actuals );
 				} // if
-				dst->base->qualifiers += src->qualifiers;
+				dst->base->qualifiers |= src->qualifiers;
 				src = nullptr;
 				break;
@@ -628,5 +621,5 @@
 						type->aggInst.hoistType = o->type->enumeration.body;
 					} // if
-					type->qualifiers += o->type->qualifiers;
+					type->qualifiers |= o->type->qualifiers;
 				} else {
 					type = o->type;
@@ -784,5 +777,5 @@
 					p->type->base->aggInst.params = maybeClone( type->aggregate.actuals );
 				} // if
-				p->type->base->qualifiers += type->qualifiers;
+				p->type->base->qualifiers |= type->qualifiers;
 				break;
 
@@ -821,5 +814,5 @@
 				lastArray->base->aggInst.params = maybeClone( type->aggregate.actuals );
 			} // if
-			lastArray->base->qualifiers += type->qualifiers;
+			lastArray->base->qualifiers |= type->qualifiers;
 			break;
 		  default:
Index: src/Parser/ExpressionNode.cc
===================================================================
--- src/Parser/ExpressionNode.cc	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/Parser/ExpressionNode.cc	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -254,4 +254,5 @@
 Expression *build_pfieldSel( ExpressionNode *expr_node, Expression *member ) {
 	UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
+	deref->location = expr_node->location;
 	deref->get_args().push_back( maybeMoveBuild< Expression >(expr_node) );
 	UntypedMemberExpr *ret = new UntypedMemberExpr( member, deref );
Index: src/Parser/ParseNode.h
===================================================================
--- src/Parser/ParseNode.h	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/Parser/ParseNode.h	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -134,4 +134,5 @@
 			Expression * p = orig->build();
 			p->set_extension( orig->get_extension() );
+			p->location = orig->location;
 			return p;
 		} else {
Index: src/Parser/TypeData.cc
===================================================================
--- src/Parser/TypeData.cc	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/Parser/TypeData.cc	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -10,6 +10,6 @@
 // Created On       : Sat May 16 15:12:51 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Mar 16 08:32:42 2017
-// Update Count     : 559
+// Last Modified On : Fri Mar 17 08:46:10 2017
+// Update Count     : 560
 //
 
@@ -227,5 +227,5 @@
 void TypeData::print( ostream &os, int indent ) const {
 	for ( int i = 0; i < Type::NumTypeQualifier; i += 1 ) {
-		if ( qualifiers[i] ) os << Type::Qualifiers::Names[ i ] << ' ';
+		if ( qualifiers[i] ) os << Type::QualifiersNames[ i ] << ' ';
 	} // for
 
Index: src/Parser/lex.ll
===================================================================
--- src/Parser/lex.ll	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/Parser/lex.ll	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -10,6 +10,6 @@
  * Created On       : Sat Sep 22 08:58:10 2001
  * Last Modified By : Peter A. Buhr
- * Last Modified On : Thu Mar  9 21:38:26 2017
- * Update Count     : 505
+ * Last Modified On : Mon Mar 13 08:36:17 2017
+ * Update Count     : 506
  */
 
@@ -313,4 +313,5 @@
 
 				/* punctuation */
+"@"				{ ASCIIOP_RETURN(); }
 "["				{ ASCIIOP_RETURN(); }
 "]"				{ ASCIIOP_RETURN(); }
Index: src/Parser/parser.yy
===================================================================
--- src/Parser/parser.yy	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/Parser/parser.yy	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -10,6 +10,6 @@
 // Created On       : Sat Sep  1 20:22:55 2001
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Mar 16 08:36:17 2017
-// Update Count     : 2310
+// Last Modified On : Thu Mar 16 12:57:03 2017
+// Update Count     : 2316
 //
 
@@ -1612,5 +1612,5 @@
 aggregate_type:											// struct, union
 	aggregate_key attribute_list_opt '{' field_declaration_list '}'
-		{ $$ = DeclarationNode::newAggregate( $1, nullptr, nullptr, $4, true )->addQualifiers( $2 ); }
+		{ $$ = DeclarationNode::newAggregate( $1, new string( DeclarationNode::anonymous.newName() ), nullptr, $4, true )->addQualifiers( $2 ); }
 	| aggregate_key attribute_list_opt no_attr_identifier_or_type_name
 		{ typedefTable.makeTypedef( *$3 ); }
@@ -1618,5 +1618,5 @@
 		{ $$ = DeclarationNode::newAggregate( $1, $3, nullptr, $6, true )->addQualifiers( $2 ); }
 	| aggregate_key attribute_list_opt '(' type_name_list ')' '{' field_declaration_list '}' // CFA
-		{ $$ = DeclarationNode::newAggregate( $1, nullptr, $4, $7, false )->addQualifiers( $2 ); }
+		{ $$ = DeclarationNode::newAggregate( $1, new string( DeclarationNode::anonymous.newName() ), $4, $7, false )->addQualifiers( $2 ); }
 	| aggregate_type_nobody
 	;
@@ -1688,6 +1688,6 @@
 	// empty
 		{ $$ = DeclarationNode::newName( 0 ); /* XXX */ } // CFA, no field name
-	// '@' // empty
-	// 	{ $$ = DeclarationNode::newName( 0 ); /* XXX */ } // CFA, no field name
+	// '@'
+	// 	{ $$ = DeclarationNode::newName( new string( DeclarationNode::anonymous.newName() ) ); } // CFA, no field name
 	| bit_subrange_size									// no field name
 		{ $$ = DeclarationNode::newBitfield( $1 ); }
@@ -1715,5 +1715,5 @@
 enum_type:												// enum
 	ENUM attribute_list_opt '{' enumerator_list comma_opt '}'
-		{ $$ = DeclarationNode::newEnum( nullptr, $4, true )->addQualifiers( $2 ); }
+		{ $$ = DeclarationNode::newEnum( new string( DeclarationNode::anonymous.newName() ), $4, true )->addQualifiers( $2 ); }
 	| ENUM attribute_list_opt no_attr_identifier_or_type_name
 		{ typedefTable.makeTypedef( *$3 ); }
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -10,6 +10,6 @@
 // Created On       : Sat May 16 23:52:08 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Mon Jul  4 17:02:51 2016
-// Update Count     : 29
+// Last Modified On : Fri Mar 17 09:14:17 2017
+// Update Count     : 30
 //
 
@@ -200,7 +200,8 @@
 		}
 
-		// Central location to handle gcc extension keyword for all expression types.
+		// Central location to handle gcc extension keyword, etc. for all expression types.
 		for ( Alternative &iter: alternatives ) {
 			iter.expr->set_extension( expr->get_extension() );
+			iter.expr->location = expr->location;
 		} // for
 	}
@@ -771,5 +772,5 @@
 	bool isLvalue( Expression *expr ) {
 		// xxx - recurse into tuples?
-		return expr->has_result() && expr->get_result()->get_isLvalue();
+		return expr->has_result() && expr->get_result()->get_lvalue();
 	}
 
Index: src/ResolvExpr/CommonType.cc
===================================================================
--- src/ResolvExpr/CommonType.cc	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/ResolvExpr/CommonType.cc	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -10,6 +10,6 @@
 // Created On       : Sun May 17 06:59:27 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Mar  2 17:35:34 2016
-// Update Count     : 3
+// Last Modified On : Thu Mar 16 16:24:31 2017
+// Update Count     : 7
 //
 
@@ -71,5 +71,5 @@
 							if ( unifyExact( type1, type->get_base(), env, have, need, newOpen, indexer ) ) {
 								result = type1->clone();
-								result->get_qualifiers() = tq1 + tq2;
+								result->get_qualifiers() = tq1 | tq2;
 							} // if
 							type1->get_qualifiers() = tq1;
@@ -133,5 +133,5 @@
 			BasicType::Kind newType = combinedType[ basicType->get_kind() ][ otherBasic->get_kind() ];
 			if ( ( ( newType == basicType->get_kind() && basicType->get_qualifiers() >= otherBasic->get_qualifiers() ) || widenFirst ) && ( ( newType == otherBasic->get_kind() && basicType->get_qualifiers() <= otherBasic->get_qualifiers() ) || widenSecond ) ) {
-				result = new BasicType( basicType->get_qualifiers() + otherBasic->get_qualifiers(), newType );
+				result = new BasicType( basicType->get_qualifiers() | otherBasic->get_qualifiers(), newType );
 			} // if
 		} else if ( dynamic_cast< EnumInstType * > ( type2 ) || dynamic_cast< ZeroType* >( type2 ) || dynamic_cast< OneType* >( type2 ) ) {
@@ -139,5 +139,5 @@
 			BasicType::Kind newType = combinedType[ basicType->get_kind() ][ BasicType::SignedInt ];
 			if ( ( ( newType == basicType->get_kind() && basicType->get_qualifiers() >= type2->get_qualifiers() ) || widenFirst ) && ( ( newType != basicType->get_kind() && basicType->get_qualifiers() <= type2->get_qualifiers() ) || widenSecond ) ) {
-				result = new BasicType( basicType->get_qualifiers() + type2->get_qualifiers(), newType );
+				result = new BasicType( basicType->get_qualifiers() | type2->get_qualifiers(), newType );
 			} // if
 		} // if
@@ -154,5 +154,5 @@
 		}
 		result = voidPointer->clone();
-		result->get_qualifiers() += otherPointer->get_qualifiers();
+		result->get_qualifiers() |= otherPointer->get_qualifiers();
 	}
 
@@ -176,5 +176,5 @@
 						result = otherPointer->clone();
 					} // if
-					result->get_qualifiers() = tq1 + tq2;
+					result->get_qualifiers() = tq1 | tq2;
 				} else {
 					/// std::cout << "place for ptr-to-type" << std::endl;
@@ -185,5 +185,5 @@
 		} else if ( widenSecond && dynamic_cast< ZeroType* >( type2 ) ) {
 			result = pointerType->clone();
-			result->get_qualifiers() += type2->get_qualifiers();
+			result->get_qualifiers() |= type2->get_qualifiers();
 		} // if
 	}
@@ -230,5 +230,5 @@
 					if ( unifyExact( type->get_base(), type2, env, have, need, newOpen, indexer ) ) {
 						result = type2->clone();
-						result->get_qualifiers() = tq1 + tq2;
+						result->get_qualifiers() = tq1 | tq2;
 					} // if
 					type2->get_qualifiers() = tq2;
@@ -250,9 +250,9 @@
 				if ( widenSecond || zeroType->get_qualifiers() <= type2->get_qualifiers() ) {
 					result = type2->clone();
-					result->get_qualifiers() += zeroType->get_qualifiers();
+					result->get_qualifiers() |= zeroType->get_qualifiers();
 				}
 			} else if ( widenSecond && dynamic_cast< OneType* >( type2 ) ) {
 				result = new BasicType( zeroType->get_qualifiers(), BasicType::SignedInt );
-				result->get_qualifiers() += type2->get_qualifiers();
+				result->get_qualifiers() |= type2->get_qualifiers();
 			}
 		}
@@ -264,9 +264,9 @@
 				if ( widenSecond || oneType->get_qualifiers() <= type2->get_qualifiers() ) {
 					result = type2->clone();
-					result->get_qualifiers() += oneType->get_qualifiers();
+					result->get_qualifiers() |= oneType->get_qualifiers();
 				}
 			} else if ( widenSecond && dynamic_cast< ZeroType* >( type2 ) ) {
 				result = new BasicType( oneType->get_qualifiers(), BasicType::SignedInt );
-				result->get_qualifiers() += type2->get_qualifiers();
+				result->get_qualifiers() |= type2->get_qualifiers();
 			}
 		}
Index: src/ResolvExpr/Unify.cc
===================================================================
--- src/ResolvExpr/Unify.cc	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/ResolvExpr/Unify.cc	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -10,6 +10,6 @@
 // Created On       : Sun May 17 12:27:10 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Mar 16 07:59:59 2017
-// Update Count     : 40
+// Last Modified On : Thu Mar 16 16:22:54 2017
+// Update Count     : 42
 //
 
@@ -353,5 +353,5 @@
 #endif
 			if ( ( common = commonType( type1, type2, widenMode.widenFirst, widenMode.widenSecond, indexer, env, openVars ) ) ) {
-				common->get_qualifiers() = tq1 + tq2;
+				common->get_qualifiers() = tq1 | tq2;
 #ifdef DEBUG
 				std::cerr << "unifyInexact: common type is ";
@@ -370,5 +370,5 @@
 				if ( ( tq1 > tq2 || widenMode.widenFirst ) && ( tq2 > tq1 || widenMode.widenSecond ) ) {
 					common = type1->clone();
-					common->get_qualifiers() = tq1 + tq2;
+					common->get_qualifiers() = tq1 | tq2;
 					result = true;
 				} else {
Index: src/SymTab/Autogen.cc
===================================================================
--- src/SymTab/Autogen.cc	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/SymTab/Autogen.cc	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -10,6 +10,6 @@
 // Created On       : Thu Mar 03 15:45:56 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Mar 16 08:37:22 2017
-// Update Count     : 59
+// Last Modified On : Fri Mar 17 09:41:08 2017
+// Update Count     : 60
 //
 
@@ -323,5 +323,5 @@
 				}
 
-				if ( type->get_qualifiers().isConst && func->get_name() == "?=?" ) {
+				if ( type->get_const() && func->get_name() == "?=?" ) {
 					// don't assign const members, but do construct/destruct
 					continue;
Index: src/SymTab/Autogen.h
===================================================================
--- src/SymTab/Autogen.h	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/SymTab/Autogen.h	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -10,6 +10,6 @@
 // Created On       : Sun May 17 21:53:34 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Mar 16 07:51:39 2017
-// Update Count     : 8
+// Last Modified On : Fri Mar 17 09:10:41 2017
+// Update Count     : 9
 //
 
@@ -60,5 +60,5 @@
 //			castType->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, false);
 			castType->get_qualifiers() -= Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
-			castType->set_isLvalue( true ); // xxx - might not need this
+			castType->set_lvalue( true ); // xxx - might not need this
 			dstParam = new CastExpr( dstParam, new PointerType( Type::Qualifiers(), castType ) );
 		}
Index: src/SymTab/ImplementationType.cc
===================================================================
--- src/SymTab/ImplementationType.cc	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/SymTab/ImplementationType.cc	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -10,6 +10,6 @@
 // Created On       : Sun May 17 21:32:01 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Mar  2 17:31:20 2016
-// Update Count     : 3
+// Last Modified On : Thu Mar 16 15:54:08 2017
+// Update Count     : 4
 //
 
@@ -105,5 +105,5 @@
 		if ( typeDecl && typeDecl->get_base() ) {
 			Type *base = implementationType( typeDecl->get_base(), indexer );
-			base->get_qualifiers() += inst->get_qualifiers();
+			base->get_qualifiers() |= inst->get_qualifiers();
 			result = base;
 		} // if
@@ -114,5 +114,5 @@
 		for ( std::list< Type* >::iterator i = tupleType->get_types().begin(); i != tupleType->get_types().end(); ++i ) {
 			Type *implType = implementationType( *i, indexer );
-			implType->get_qualifiers() += tupleType->get_qualifiers();
+			implType->get_qualifiers() |= tupleType->get_qualifiers();
 			newType->get_types().push_back( implType );
 		} // for
Index: src/SymTab/Mangler.cc
===================================================================
--- src/SymTab/Mangler.cc	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/SymTab/Mangler.cc	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -9,7 +9,7 @@
 // Author           : Richard C. Bilson
 // Created On       : Sun May 17 21:40:29 2015
-// Last Modified By : Rob Schluntz
-// Last Modified On : Wed Aug 19 15:52:24 2015
-// Update Count     : 19
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Fri Mar 17 09:40:01 2017
+// Update Count     : 20
 //
 
@@ -294,8 +294,8 @@
 			mangleName << "_";
 		} // if
-		if ( type->get_isConst() ) {
+		if ( type->get_const() ) {
 			mangleName << "C";
 		} // if
-		if ( type->get_isVolatile() ) {
+		if ( type->get_volatile() ) {
 			mangleName << "V";
 		} // if
@@ -304,8 +304,8 @@
 //			mangleName << "R";
 //		} // if
-		if ( type->get_isLvalue() ) {
+		if ( type->get_lvalue() ) {
 			mangleName << "L";
 		} // if
-		if ( type->get_isAtomic() ) {
+		if ( type->get_atomic() ) {
 			mangleName << "A";
 		} // if
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/SymTab/Validate.cc	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -10,6 +10,6 @@
 // Created On       : Sun May 17 21:50:04 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Mar 16 08:02:54 2017
-// Update Count     : 351
+// Last Modified On : Thu Mar 16 16:39:15 2017
+// Update Count     : 353
 //
 
@@ -611,5 +611,5 @@
 		if ( def != typedefNames.end() ) {
 			Type *ret = def->second.first->get_base()->clone();
-			ret->get_qualifiers() += typeInst->get_qualifiers();
+			ret->get_qualifiers() |= typeInst->get_qualifiers();
 			// place instance parameters on the typedef'd type
 			if ( ! typeInst->get_parameters().empty() ) {
@@ -656,9 +656,11 @@
 		// hence the type-name "screen" must be defined.
 		// Note, qualifiers on the typedef are superfluous for the forward declaration.
-		if ( StructInstType *aggDecl = dynamic_cast< StructInstType * >( tyDecl->get_base() ) ) {
+
+		Type *designatorType = tyDecl->get_base()->stripDeclarator();
+		if ( StructInstType *aggDecl = dynamic_cast< StructInstType * >( designatorType ) ) {
 			return new StructDecl( aggDecl->get_name() );
-		} else if ( UnionInstType *aggDecl = dynamic_cast< UnionInstType * >( tyDecl->get_base() ) ) {
+		} else if ( UnionInstType *aggDecl = dynamic_cast< UnionInstType * >( designatorType ) ) {
 			return new UnionDecl( aggDecl->get_name() );
-		} else if ( EnumInstType *enumDecl = dynamic_cast< EnumInstType * >( tyDecl->get_base() ) ) {
+		} else if ( EnumInstType *enumDecl = dynamic_cast< EnumInstType * >( designatorType ) ) {
 			return new EnumDecl( enumDecl->get_name() );
 		} else {
Index: src/SynTree/ArrayType.cc
===================================================================
--- src/SynTree/ArrayType.cc	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ 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/Declaration.cc
===================================================================
--- src/SynTree/Declaration.cc	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/SynTree/Declaration.cc	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -32,5 +32,5 @@
 
 Declaration::Declaration( const Declaration &other )
-	: name( other.name ), storageClasses( other.storageClasses ), linkage( other.linkage ), uniqueId( other.uniqueId ) {
+	: BaseSyntaxNode( other ), name( other.name ), storageClasses( other.storageClasses ), linkage( other.linkage ), uniqueId( other.uniqueId ) {
 }
 
Index: src/SynTree/Expression.cc
===================================================================
--- src/SynTree/Expression.cc	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ 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
 //
 
@@ -33,5 +33,5 @@
 Expression::Expression( Expression *_aname ) : result( 0 ), env( 0 ), argName( _aname ) {}
 
-Expression::Expression( const Expression &other ) : result( maybeClone( other.result ) ), env( maybeClone( other.env ) ), argName( maybeClone( other.get_argName() ) ), extension( other.extension ) {
+Expression::Expression( const Expression &other ) : BaseSyntaxNode( other ), result( maybeClone( other.result ) ), env( maybeClone( other.env ) ), argName( maybeClone( other.get_argName() ) ), extension( other.extension ) {
 }
 
@@ -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/Initializer.cc
===================================================================
--- src/SynTree/Initializer.cc	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/SynTree/Initializer.cc	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -20,5 +20,5 @@
 
 Initializer::Initializer( bool maybeConstructed ) : maybeConstructed( maybeConstructed ) {}
-Initializer::Initializer( const Initializer & other ) : maybeConstructed( other.maybeConstructed ) {
+Initializer::Initializer( const Initializer & other ) : BaseSyntaxNode( other ), maybeConstructed( other.maybeConstructed ) {
 }
 
Index: src/SynTree/Initializer.h
===================================================================
--- src/SynTree/Initializer.h	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/SynTree/Initializer.h	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -112,4 +112,6 @@
 // ConstructorInit represents an initializer that is either a constructor expression or
 // a C-style initializer.
+// It should not be necessary to create ConstructorInit nodes manually. Instead, set maybeConstructed
+// to true on SingleInit or ListInit constructors if object should be constructed.
 class ConstructorInit : public Initializer {
   public:
Index: src/SynTree/TupleExpr.cc
===================================================================
--- src/SynTree/TupleExpr.cc	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ 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 b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ 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"
 
@@ -49,5 +50,5 @@
 Type::Type( const Qualifiers &tq, const std::list< Attribute * > & attributes ) : tq( tq ), attributes( attributes ) {}
 
-Type::Type( const Type &other ) : tq( other.tq ) {
+Type::Type( const Type &other ) : BaseSyntaxNode( other ), tq( other.tq ) {
 	cloneAll( other.forall, forall );
 	cloneAll( other.attributes, attributes );
@@ -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 {
@@ -75,5 +84,5 @@
 		printAll( attributes, os, indent+4 );
 	} // if
-	
+
 	tq.print( os );
 }
Index: src/SynTree/Type.h
===================================================================
--- src/SynTree/Type.h	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ 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 b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ 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;
Index: src/Tuples/TupleAssignment.cc
===================================================================
--- src/Tuples/TupleAssignment.cc	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/Tuples/TupleAssignment.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 08:04:51 2017
-// Update Count     : 7
+// Last Modified On : Fri Mar 17 09:43:03 2017
+// Update Count     : 8
 //
 
@@ -200,5 +200,5 @@
 				assert( type );
 				type->get_qualifiers() -= Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
-				type->set_isLvalue( true ); // xxx - might not need this
+				type->set_lvalue( true ); // xxx - might not need this
 				expr = new CastExpr( expr, castType );
 			}
Index: src/Tuples/TupleExpansion.cc
===================================================================
--- src/Tuples/TupleExpansion.cc	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/Tuples/TupleExpansion.cc	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -126,11 +126,12 @@
 		/// given a expression representing the member and an expression representing the aggregate,
 		/// reconstructs a flattened UntypedMemberExpr with the right precedence
-		Expression * reconstructMemberExpr( Expression * member, Expression * aggr ) {
+		Expression * reconstructMemberExpr( Expression * member, Expression * aggr, CodeLocation & loc ) {
 			if ( UntypedMemberExpr * memberExpr = dynamic_cast< UntypedMemberExpr * >( member ) ) {
 				// construct a new UntypedMemberExpr with the correct structure , and recursively
 				// expand that member expression.
 				MemberTupleExpander expander;
-				UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( memberExpr->get_member(), new UntypedMemberExpr( memberExpr->get_aggregate(), aggr->clone() ) );
-
+				UntypedMemberExpr * inner = new UntypedMemberExpr( memberExpr->get_aggregate(), aggr->clone() );
+				UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( memberExpr->get_member(), inner );
+				inner->location = newMemberExpr->location = loc;
 				memberExpr->set_member(nullptr);
 				memberExpr->set_aggregate(nullptr);
@@ -139,5 +140,7 @@
 			} else {
 				// not a member expression, so there is nothing to do but attach and return
-				return new UntypedMemberExpr( member, aggr->clone() );
+				UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( member, aggr->clone() );
+				newMemberExpr->location = loc;
+				return newMemberExpr;
 			}
 		}
@@ -152,12 +155,16 @@
 			aggr = new UniqueExpr( aggr );
 			for ( Expression *& expr : tupleExpr->get_exprs() ) {
-				expr = reconstructMemberExpr( expr, aggr );
+				expr = reconstructMemberExpr( expr, aggr, memberExpr->location );
+				expr->location = memberExpr->location;
 			}
 			delete aggr;
+			tupleExpr->location = memberExpr->location;
 			return tupleExpr;
 		} else {
 			// there may be a tuple expr buried in the aggregate
 			// xxx - this is a memory leak
-			return new UntypedMemberExpr( memberExpr->get_member()->clone(), memberExpr->get_aggregate()->acceptMutator( *this ) );
+			UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( memberExpr->get_member()->clone(), memberExpr->get_aggregate()->acceptMutator( *this ) );
+			newMemberExpr->location = memberExpr->location;
+			return newMemberExpr;
 		}
 	}
Index: src/tests/.expect/memberCtors-ERR1.txt
===================================================================
--- src/tests/.expect/memberCtors-ERR1.txt	(revision b32ada3178d846d1ee56e8cdd6c3755f2d532471)
+++ src/tests/.expect/memberCtors-ERR1.txt	(revision 7c700890e7a60235a8c2486a9ee74d5b67a7024f)
@@ -1,2 +1,2 @@
-error: in void ?{}(struct B *b), field a2 used before being constructed
+memberCtors.c:62 error: in void ?{}(struct B *b), field a2 used before being constructed
 make: *** [memberCtors-ERR1] Error 1
