Index: src/Parser/DeclarationNode.cc
===================================================================
--- src/Parser/DeclarationNode.cc	(revision 43c89a78fd93abc599e03ce30605af5a82c4e1cc)
+++ src/Parser/DeclarationNode.cc	(revision 3f80888109335741bb6336c1e8cace9fe2ea46cb)
@@ -10,6 +10,6 @@
 // Created On       : Sat May 16 12:34:05 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Feb 23 22:21:06 2017
-// Update Count     : 775
+// Last Modified On : Fri Mar  3 21:38:34 2017
+// Update Count     : 862
 //
 
@@ -32,13 +32,14 @@
 
 // These must remain in the same order as the corresponding DeclarationNode enumerations.
-const char * DeclarationNode::storageName[] = { "extern", "static", "auto", "register", "inline", "fortran", "_Noreturn", "_Thread_local", "NoStorageClass" };
-const char * DeclarationNode::qualifierName[] = { "const", "restrict", "volatile", "lvalue", "_Atomic", "NoQualifier" };
-const char * DeclarationNode::basicTypeName[] = { "void", "_Bool", "char", "int", "float", "double", "long double", "NoBasicType" };
-const char * DeclarationNode::complexTypeName[] = { "_Complex", "_Imaginary", "NoComplexType" };
-const char * DeclarationNode::signednessName[] = { "signed", "unsigned", "NoSignedness" };
-const char * DeclarationNode::lengthName[] = { "short", "long", "long long", "NoLength" };
-const char * DeclarationNode::aggregateName[] = { "struct", "union", "context" };
-const char * DeclarationNode::typeClassName[] = { "otype", "dtype", "ftype" };
-const char * DeclarationNode::builtinTypeName[] = { "__builtin_va_list" };
+const char * DeclarationNode::storageClassNames[] = { "extern", "static", "auto", "register", "_Thread_local", "inline", "fortran", "_Noreturn", "NoStorageClassNames" };
+const char * DeclarationNode::funcSpecifierNames[] = { "inline", "fortran", "_Noreturn", "NoFunctionSpecifierNames" };
+const char * DeclarationNode::typeQualifierNames[] = { "const", "restrict", "volatile", "lvalue", "_Atomic", "NoTypeQualifierNames" };
+const char * DeclarationNode::basicTypeNames[] = { "void", "_Bool", "char", "int", "float", "double", "long double", "NoBasicTypeNames" };
+const char * DeclarationNode::complexTypeNames[] = { "_Complex", "_Imaginary", "NoComplexTypeNames" };
+const char * DeclarationNode::signednessNames[] = { "signed", "unsigned", "NoSignednessNames" };
+const char * DeclarationNode::lengthNames[] = { "short", "long", "long long", "NoLengthNames" };
+const char * DeclarationNode::aggregateNames[] = { "struct", "union", "context", "NoAggregateNames" };
+const char * DeclarationNode::typeClassNames[] = { "otype", "dtype", "ftype", "NoTypeClassNames" };
+const char * DeclarationNode::builtinTypeNames[] = { "__builtin_va_list", "NoBuiltinTypeNames" };
 
 UniqueName DeclarationNode::anonymous( "__anonymous" );
@@ -50,6 +51,4 @@
 		storageClass( NoStorageClass ),
 		bitfieldWidth( nullptr ),
-		isInline( false ),
-		isNoreturn( false ),
 		hasEllipsis( false ),
 		linkage( ::linkage ),
@@ -92,6 +91,5 @@
 	newnode->storageClass = storageClass;
 	newnode->bitfieldWidth = maybeClone( bitfieldWidth );
-	newnode->isInline = isInline;
-	newnode->isNoreturn = isNoreturn;
+	newnode->funcSpec = funcSpec;
 	newnode->enumeratorValue.reset( maybeClone( enumeratorValue.get() ) );
 	newnode->hasEllipsis = hasEllipsis;
@@ -118,4 +116,14 @@
 }
 
+void DeclarationNode::print_FuncSpec( std::ostream & output, DeclarationNode::FuncSpec funcSpec ) {
+	if ( funcSpec.any() ) {								// function specifiers?
+		for ( unsigned int i = 0; i < DeclarationNode::NoFuncSpecifier; i += 1 ) {
+			if ( funcSpec[i] ) {
+				output << DeclarationNode::funcSpecifierNames[i] << ' ';
+			} // if
+		} // for
+	} // if
+} // print_FuncSpec
+
 void DeclarationNode::print( std::ostream &os, int indent ) const {
 	os << string( indent, ' ' );
@@ -130,7 +138,7 @@
 	} // if
 
-	if ( storageClass != NoStorageClass ) os << DeclarationNode::storageName[storageClass] << ' ';
-	if ( isInline ) os << DeclarationNode::storageName[Inline] << ' ';
-	if ( isNoreturn ) os << DeclarationNode::storageName[Noreturn] << ' ';
+	if ( storageClass != NoStorageClass ) os << DeclarationNode::storageClassNames[storageClass] << ' ';
+	print_FuncSpec( os, funcSpec );
+
 	if ( type ) {
 		type->print( os, indent );
@@ -183,10 +191,51 @@
 } // DeclarationNode::newFunction
 
-DeclarationNode * DeclarationNode::newQualifier( Qualifier q ) {
+
+DeclarationNode * DeclarationNode::newStorageClass( DeclarationNode::StorageClass sc ) {
+	DeclarationNode * newnode = new DeclarationNode;
+	newnode->storageClass = sc;
+	return newnode;
+} // DeclarationNode::newStorageClass
+
+DeclarationNode * DeclarationNode::newFuncSpecifier( DeclarationNode::FuncSpecifier fs ) {
+	DeclarationNode * newnode = new DeclarationNode;
+	newnode->funcSpec[ fs ] = true;
+	return newnode;
+} // DeclarationNode::newFuncSpecifier
+
+DeclarationNode * DeclarationNode::newTypeQualifier( TypeQualifier tq ) {
 	DeclarationNode * newnode = new DeclarationNode;
 	newnode->type = new TypeData();
-	newnode->type->qualifiers[ q ] = 1;
+	newnode->type->typeQualifiers[ tq ] = true;
 	return newnode;
 } // DeclarationNode::newQualifier
+
+DeclarationNode * DeclarationNode::newBasicType( BasicType bt ) {
+	DeclarationNode * newnode = new DeclarationNode;
+	newnode->type = new TypeData( TypeData::Basic );
+	newnode->type->basictype = bt;
+	return newnode;
+} // DeclarationNode::newBasicType
+
+DeclarationNode * DeclarationNode::newComplexType( ComplexType ct ) {
+	DeclarationNode * newnode = new DeclarationNode;
+	newnode->type = new TypeData( TypeData::Basic );
+	newnode->type->complextype = ct;
+	return newnode;
+} // DeclarationNode::newComplexType
+
+DeclarationNode * DeclarationNode::newSignedNess( Signedness sn ) {
+	DeclarationNode * newnode = new DeclarationNode;
+	newnode->type = new TypeData( TypeData::Basic );
+	newnode->type->signedness = sn;
+	return newnode;
+} // DeclarationNode::newSignedNess
+
+DeclarationNode * DeclarationNode::newLength( Length lnth ) {
+	DeclarationNode * newnode = new DeclarationNode;
+	newnode->type = new TypeData( TypeData::Basic );
+	newnode->type->length = lnth;
+	return newnode;
+} // DeclarationNode::newLength
 
 DeclarationNode * DeclarationNode::newForall( DeclarationNode * forall ) {
@@ -196,38 +245,4 @@
 	return newnode;
 } // DeclarationNode::newForall
-
-DeclarationNode * DeclarationNode::newStorageClass( DeclarationNode::StorageClass sc ) {
-	DeclarationNode * newnode = new DeclarationNode;
-	newnode->storageClass = sc;
-	return newnode;
-} // DeclarationNode::newStorageClass
-
-DeclarationNode * DeclarationNode::newBasicType( BasicType bt ) {
-	DeclarationNode * newnode = new DeclarationNode;
-	newnode->type = new TypeData( TypeData::Basic );
-	newnode->type->basictype = bt;
-	return newnode;
-} // DeclarationNode::newBasicType
-
-DeclarationNode * DeclarationNode::newComplexType( ComplexType ct ) {
-	DeclarationNode * newnode = new DeclarationNode;
-	newnode->type = new TypeData( TypeData::Basic );
-	newnode->type->complextype = ct;
-	return newnode;
-} // DeclarationNode::newComplexType
-
-DeclarationNode * DeclarationNode::newSignedNess( Signedness sn ) {
-	DeclarationNode * newnode = new DeclarationNode;
-	newnode->type = new TypeData( TypeData::Basic );
-	newnode->type->signedness = sn;
-	return newnode;
-} // DeclarationNode::newSignedNess
-
-DeclarationNode * DeclarationNode::newLength( Length lnth ) {
-	DeclarationNode * newnode = new DeclarationNode;
-	newnode->type = new TypeData( TypeData::Basic );
-	newnode->type->length = lnth;
-	return newnode;
-} // DeclarationNode::newLength
 
 DeclarationNode * DeclarationNode::newFromTypedef( string * name ) {
@@ -428,10 +443,10 @@
 
 void DeclarationNode::checkQualifiers( const TypeData * src, const TypeData * dst ) {
-	TypeData::Qualifiers qsrc = src->qualifiers, qdst = dst->qualifiers; // optimization
-
-	if ( (qsrc & qdst).any() ) {						// common qualifier ?
-		for ( int i = 0; i < NoQualifier; i += 1 ) {	// find common qualifiers
+	const TypeData::TypeQualifiers &qsrc = src->typeQualifiers, &qdst = dst->typeQualifiers; // optimization
+
+	if ( (qsrc & qdst).any() ) {						 // common qualifier ?
+		for ( unsigned int i = 0; i < NoTypeQualifier; i += 1 ) { // find common qualifiers
 			if ( qsrc[i] && qdst[i] ) {
-				appendError( error, string( "duplicate " ) + DeclarationNode::qualifierName[i] );
+				appendError( error, string( "duplicate " ) + DeclarationNode::typeQualifierNames[i] );
 			} // if
 		} // for
@@ -440,18 +455,28 @@
 
 void DeclarationNode::checkStorageClasses( DeclarationNode * q ) {
+	const FuncSpec &src = funcSpec, &dst = q->funcSpec; // optimization
+	if ( (src & dst).any() ) {							// common specifier ?
+		for ( unsigned int i = 0; i < NoFuncSpecifier; i += 1 ) { // find common specifier
+			if ( src[i] && dst[i] ) {
+				appendError( error, string( "duplicate " ) + DeclarationNode::funcSpecifierNames[i] );
+			} // if
+		} // for
+	} // if
+
 	if ( storageClass != NoStorageClass && q->storageClass != NoStorageClass ) {
 		if ( storageClass == q->storageClass ) {		// duplicate qualifier
-			appendError( error, string( "duplicate " ) + storageName[ storageClass ] );
+			appendError( error, string( "duplicate " ) + storageClassNames[ storageClass ] );
 		} else {										// only one storage class
-			appendError( error, string( "conflicting " ) + storageName[ storageClass ] + " & " + storageName[ q->storageClass ] );
+			appendError( error, string( "conflicting " ) + storageClassNames[ storageClass ] + " & " + storageClassNames[ q->storageClass ] );
 			q->storageClass = storageClass;				// FIX ERROR, prevent assertions from triggering
 		} // if
 	} // if
+
 	appendError( error, q->error );
 } // DeclarationNode::checkStorageClasses
 
 DeclarationNode * DeclarationNode::copyStorageClasses( DeclarationNode * q ) {
-	isInline = isInline || q->isInline;
-	isNoreturn = isNoreturn || q->isNoreturn;
+	funcSpec = funcSpec | q->funcSpec;
+
 	// do not overwrite an existing value with NoStorageClass
 	if ( q->storageClass != NoStorageClass ) {
@@ -481,5 +506,5 @@
 		src = nullptr;
 	} else {
-		dst->qualifiers |= src->qualifiers;
+		dst->typeQualifiers |= src->typeQualifiers;
 	} // if
 } // addQualifiersToType
@@ -539,10 +564,10 @@
 		switch ( dst->kind ) {
 		  case TypeData::Unknown:
-			src->qualifiers |= dst->qualifiers;
+			src->typeQualifiers |= dst->typeQualifiers;
 			dst = src;
 			src = nullptr;
 			break;
 		  case TypeData::Basic:
-			dst->qualifiers |= src->qualifiers;
+			dst->typeQualifiers |= src->typeQualifiers;
 			if ( src->kind != TypeData::Unknown ) {
 				assert( src->kind == TypeData::Basic );
@@ -551,15 +576,15 @@
 					dst->basictype = src->basictype;
 				} else if ( src->basictype != DeclarationNode::NoBasicType )
-					throw SemanticError( string( "conflicting type specifier " ) + DeclarationNode::basicTypeName[ src->basictype ] + " in type: ", src );
+					throw SemanticError( string( "conflicting type specifier " ) + DeclarationNode::basicTypeNames[ src->basictype ] + " in type: ", src );
 
 				if ( dst->complextype == DeclarationNode::NoComplexType ) {
 					dst->complextype = src->complextype;
 				} else if ( src->complextype != DeclarationNode::NoComplexType )
-					throw SemanticError( string( "conflicting type specifier " ) + DeclarationNode::complexTypeName[ src->complextype ] + " in type: ", src );
+					throw SemanticError( string( "conflicting type specifier " ) + DeclarationNode::complexTypeNames[ src->complextype ] + " in type: ", src );
 
 				if ( dst->signedness == DeclarationNode::NoSignedness ) {
 					dst->signedness = src->signedness;
 				} else if ( src->signedness != DeclarationNode::NoSignedness )
-					throw SemanticError( string( "conflicting type specifier " ) + DeclarationNode::signednessName[ src->signedness ] + " in type: ", src );
+					throw SemanticError( string( "conflicting type specifier " ) + DeclarationNode::signednessNames[ src->signedness ] + " in type: ", src );
 
 				if ( dst->length == DeclarationNode::NoLength ) {
@@ -568,5 +593,5 @@
 					dst->length = DeclarationNode::LongLong;
 				} else if ( src->length != DeclarationNode::NoLength )
-					throw SemanticError( string( "conflicting type specifier " ) + DeclarationNode::lengthName[ src->length ] + " in type: ", src );
+					throw SemanticError( string( "conflicting type specifier " ) + DeclarationNode::lengthNames[ src->length ] + " in type: ", src );
 			} // if
 			break;
@@ -580,5 +605,5 @@
 					dst->base->aggInst.params = maybeClone( src->aggregate.actuals );
 				} // if
-				dst->base->qualifiers |= src->qualifiers;
+				dst->base->typeQualifiers |= src->typeQualifiers;
 				src = nullptr;
 				break;
@@ -612,5 +637,5 @@
 						type->aggInst.hoistType = o->type->enumeration.body;
 					} // if
-					type->qualifiers |= o->type->qualifiers;
+					type->typeQualifiers |= o->type->typeQualifiers;
 				} else {
 					type = o->type;
@@ -768,5 +793,5 @@
 					p->type->base->aggInst.params = maybeClone( type->aggregate.actuals );
 				} // if
-				p->type->base->qualifiers |= type->qualifiers;
+				p->type->base->typeQualifiers |= type->typeQualifiers;
 				break;
 
@@ -805,5 +830,5 @@
 					lastArray->base->aggInst.params = maybeClone( type->aggregate.actuals );
 				} // if
-				lastArray->base->qualifiers |= type->qualifiers;
+				lastArray->base->typeQualifiers |= type->typeQualifiers;
 				break;
 			  default:
@@ -1005,10 +1030,8 @@
 	} // if
 
-//	if ( variable.name ) {
 	if ( variable.tyClass != NoTypeClass ) {
 		static const TypeDecl::Kind kindMap[] = { TypeDecl::Any, TypeDecl::Dtype, TypeDecl::Ftype, TypeDecl::Ttype };
 		assertf( sizeof(kindMap)/sizeof(kindMap[0] == NoTypeClass-1), "DeclarationNode::build: kindMap is out of sync." );
 		assertf( variable.tyClass < sizeof(kindMap)/sizeof(kindMap[0]), "Variable's tyClass is out of bounds." );
-//		TypeDecl * ret = new TypeDecl( *variable.name, DeclarationNode::NoStorageClass, nullptr, kindMap[ variable.tyClass ] );
 		TypeDecl * ret = new TypeDecl( *name, DeclarationNode::NoStorageClass, nullptr, kindMap[ variable.tyClass ] );
 		buildList( variable.assertions, ret->get_assertions() );
@@ -1017,13 +1040,24 @@
 
 	if ( type ) {
-		return buildDecl( type, name ? *name : string( "" ), storageClass, maybeBuild< Expression >( bitfieldWidth ), isInline, isNoreturn, linkage, asmName, maybeBuild< Initializer >(initializer), attributes )->set_extension( extension );
-	} // if
-
-	if ( ! isInline && ! isNoreturn ) {
-		assertf( name, "ObjectDecl are assumed to have names\n" );
-		return (new ObjectDecl( *name, storageClass, linkage, maybeBuild< Expression >( bitfieldWidth ), nullptr, maybeBuild< Initializer >( initializer ) ))->set_asmName( asmName )->set_extension( extension );
-	} // if
-
-	throw SemanticError( "invalid function specifier ", this );
+		// Function specifiers can only appear on a function definition/declaration.
+		//
+		//    inline _Noreturn int f();			// allowed
+		//    inline _Noreturn int g( int i );	// allowed
+		//    inline _Noreturn int i;			// disallowed
+		if ( type->kind != TypeData::Function && funcSpec.any() ) {
+			throw SemanticError( "invalid function specifier for ", this );
+		} // if
+		return buildDecl( type, name ? *name : string( "" ), storageClass, maybeBuild< Expression >( bitfieldWidth ), funcSpec, linkage, asmName, maybeBuild< Initializer >(initializer), attributes )->set_extension( extension );
+	} // if
+
+	// SUE's cannot have function specifiers, either
+	//
+	//    inlne _Noreturn struct S { ... };		// disallowed
+	//    inlne _Noreturn enum   E { ... };		// disallowed
+	if ( funcSpec.any() ) {
+		throw SemanticError( "invalid function specifier for ", this );
+	} // if
+	assertf( name, "ObjectDecl must a have name\n" );
+	return (new ObjectDecl( *name, storageClass, linkage, maybeBuild< Expression >( bitfieldWidth ), nullptr, maybeBuild< Initializer >( initializer ) ))->set_asmName( asmName )->set_extension( extension );
 }
 
@@ -1032,8 +1066,6 @@
 
 	if ( attr.expr ) {
-//		return new AttrType( buildQualifiers( type ), *attr.name, attr.expr->build() );
 		return new AttrType( buildQualifiers( type ), *name, attr.expr->build(), attributes );
 	} else if ( attr.type ) {
-//		return new AttrType( buildQualifiers( type ), *attr.name, attr.type->buildType() );
 		return new AttrType( buildQualifiers( type ), *name, attr.type->buildType(), attributes );
 	} // if
