Index: src/AST/Decl.cpp
===================================================================
--- src/AST/Decl.cpp	(revision bbbff10c7298866851953ec442ea30d05e91b2a8)
+++ src/AST/Decl.cpp	(revision 90e683bd043dbecee5fc34eec99bc3d53f59d082)
@@ -169,8 +169,4 @@
 }
 
-bool EnumDecl::isTyped() const { return base; }
-
-bool EnumDecl::isOpaque() const { return isCfa && !isTyped(); }
-
 }
 
Index: src/AST/Decl.hpp
===================================================================
--- src/AST/Decl.hpp	(revision bbbff10c7298866851953ec442ea30d05e91b2a8)
+++ src/AST/Decl.hpp	(revision 90e683bd043dbecee5fc34eec99bc3d53f59d082)
@@ -306,5 +306,5 @@
 enum class EnumAttribute{ Value, Posn, Label };
 
-/// enum declaration `enum Foo { ... };`
+/// enum declaration `enum Foo { ... };` or `enum(...) Foo { ... };`
 class EnumDecl final : public AggregateDecl {
 public:
@@ -317,4 +317,8 @@
 	std::vector< ast::ptr<ast::EnumInstType>> inlinedDecl; // child enums
 
+	bool is_c_enum     () const { return !isCfa; }
+	bool is_opaque_enum() const { return isCfa && nullptr == base; }
+	bool is_typed_enum () const { return isCfa && nullptr != base; }
+
 	EnumDecl( const CodeLocation& loc, const std::string& name, bool isCfa = false,
 		std::vector<ptr<Attribute>>&& attrs = {}, Linkage::Spec linkage = Linkage::Cforall,
@@ -331,6 +335,4 @@
 	const char * typeString() const override { return aggrString( Enum ); }
 
-	bool isTyped() const;
-	bool isOpaque() const;
 private:
 	EnumDecl * clone() const override { return new EnumDecl{ *this }; }
Index: src/AST/Util.cpp
===================================================================
--- src/AST/Util.cpp	(revision bbbff10c7298866851953ec442ea30d05e91b2a8)
+++ src/AST/Util.cpp	(revision 90e683bd043dbecee5fc34eec99bc3d53f59d082)
@@ -85,4 +85,11 @@
 	// Check that `type->returns` corresponds with `decl->returns`.
 	assert( type->returns.size() == decl->returns.size() );
+}
+
+/// Check that an enumeration has not been made with an inconsistent spec.
+void isEnumerationConsistent( const EnumDecl * node ) {
+	if ( node->is_c_enum() ) {
+		assert( nullptr == node->base );
+	}
 }
 
@@ -135,4 +142,9 @@
 		previsit( (const ParseNode *)node );
 		functionDeclMatchesType( node );
+	}
+
+	void previsit( const EnumDecl * node ) {
+		previsit( (const ParseNode *)node );
+		isEnumerationConsistent( node );
 	}
 
Index: src/InitTweak/GenInit.cpp
===================================================================
--- src/InitTweak/GenInit.cpp	(revision bbbff10c7298866851953ec442ea30d05e91b2a8)
+++ src/InitTweak/GenInit.cpp	(revision 90e683bd043dbecee5fc34eec99bc3d53f59d082)
@@ -164,20 +164,16 @@
 				ast::ObjectDecl * arrayDimension = nullptr;
 
-				const ast::TypeExpr * ty = dynamic_cast< const ast::TypeExpr * >( arrayType->dimension.get() );
-				if ( ty ) {
+				if ( auto ty = dynamic_cast< const ast::TypeExpr * >( arrayType->dimension.get() ) ) {
 					auto inst = ty->type.as<ast::EnumInstType>();
-					if ( inst ) {
-						if ( inst->base->isCfa ) {
-							arrayDimension = new ast::ObjectDecl(
+					if ( inst && !inst->base->is_c_enum() ) {
+						arrayDimension = new ast::ObjectDecl(
+							arrayType->dimension->location,
+							dimensionName.newName(),
+							new ast::BasicType( ast::BasicKind::UnsignedChar ),
+							new ast::SingleInit(
 								arrayType->dimension->location,
-								dimensionName.newName(),
-								new ast::BasicType( ast::BasicKind::UnsignedChar ),
-								new ast::SingleInit(
-									arrayType->dimension->location,
-									ast::ConstantExpr::from_int( arrayType->dimension->location, inst->base->members.size() )
-								)
-							);
-							// return arrayType;
-						}
+								ast::ConstantExpr::from_int( arrayType->dimension->location, inst->base->members.size() )
+							)
+						);
 					}
 				}
Index: src/Parser/TypeData.cpp
===================================================================
--- src/Parser/TypeData.cpp	(revision bbbff10c7298866851953ec442ea30d05e91b2a8)
+++ src/Parser/TypeData.cpp	(revision 90e683bd043dbecee5fc34eec99bc3d53f59d082)
@@ -1482,9 +1482,9 @@
 		object->isHidden = ast::EnumDecl::EnumHiding::Hide == ret->hide;
 		object->isMember = true;
-		if ( ret->isOpaque() && cur->has_enumeratorValue() ) {
+		if ( ret->is_opaque_enum() && cur->has_enumeratorValue() ) {
 			SemanticError( td->location, "Opague cannot have an explicit initializer value." );
 		} else if ( cur->has_enumeratorValue() ) {
 			ast::Expr * initValue;
-			if ( ret->isCfa && ret->base ) {
+			if ( ret->is_typed_enum() ) {
 				CodeLocation location = cur->enumeratorValue->location;
 				initValue = new ast::CastExpr( location, maybeMoveBuild( cur->consume_enumeratorValue() ), ret->base );
Index: src/ResolvExpr/CastCost.cpp
===================================================================
--- src/ResolvExpr/CastCost.cpp	(revision bbbff10c7298866851953ec442ea30d05e91b2a8)
+++ src/ResolvExpr/CastCost.cpp	(revision 90e683bd043dbecee5fc34eec99bc3d53f59d082)
@@ -53,13 +53,13 @@
 		void postvisit( const ast::EnumInstType * enumInst ) {
 			cost = conversionCost( enumInst, dst, srcIsLvalue, symtab, env );
-			if ( enumInst->base->isTyped() ) {
-				auto baseConversionCost = 
+			if ( enumInst->base->is_typed_enum() ) {
+				auto baseConversionCost =
 					castCost( enumInst->base->base, dst, srcIsLvalue, symtab, env );
-				cost = baseConversionCost < cost? baseConversionCost: cost;
+				cost = baseConversionCost < cost ? baseConversionCost : cost;
 			}
 			static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicKind::SignedInt ) };
 			Cost intCost = costCalc( integer, dst, srcIsLvalue, symtab, env );
 			intCost.incSafe();
-			cost = intCost < cost? intCost: cost;
+			cost = intCost < cost ? intCost : cost;
 		}
 
Index: src/ResolvExpr/CommonType.cpp
===================================================================
--- src/ResolvExpr/CommonType.cpp	(revision bbbff10c7298866851953ec442ea30d05e91b2a8)
+++ src/ResolvExpr/CommonType.cpp	(revision 90e683bd043dbecee5fc34eec99bc3d53f59d082)
@@ -386,5 +386,5 @@
 		} else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( type2 ) ) {
 			const ast::EnumDecl* enumDecl = enumInst->base;
-			if ( !enumDecl->isCfa  ) {
+			if ( enumDecl->is_c_enum() ) {
 				ast::BasicKind kind = commonTypes[ basic->kind ][ ast::BasicKind::SignedInt ];
 				if (
@@ -654,5 +654,5 @@
 				result = param;
 			}
-		} else if ( param->base && !param->base->isCfa ) {
+		} else if ( param->base && param->base->is_c_enum() ) {
 			auto basicType = new ast::BasicType( ast::BasicKind::UnsignedInt );
 			result = commonType( basicType, type2, tenv, need, have, open, widen);
Index: src/ResolvExpr/ConversionCost.cpp
===================================================================
--- src/ResolvExpr/ConversionCost.cpp	(revision bbbff10c7298866851953ec442ea30d05e91b2a8)
+++ src/ResolvExpr/ConversionCost.cpp	(revision 90e683bd043dbecee5fc34eec99bc3d53f59d082)
@@ -246,5 +246,5 @@
 		}
 		if (const ast::EnumInstType * srcAsInst = dynamic_cast< const ast::EnumInstType * >( src )) {
-			if (srcAsInst->base && !srcAsInst->base->isCfa) {
+			if ( srcAsInst->base && srcAsInst->base->is_c_enum() ) {
 				static const ast::BasicType* integer = new ast::BasicType( ast::BasicKind::UnsignedInt );
 				return ast::Pass<ConversionCost>::read( integer, dst, srcIsLvalue, symtab, env, conversionCost );
@@ -324,5 +324,5 @@
 		conversionCostFromBasicToBasic( basicType, dstAsBasic );
 	} else if ( auto dstAsEnumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) {
-		if ( dstAsEnumInst->base && !dstAsEnumInst->base->isCfa ) {
+		if ( dstAsEnumInst->base && dstAsEnumInst->base->is_c_enum() ) {
 			cost = Cost::safe;
 		}
@@ -405,5 +405,5 @@
 	if ( auto dstInst = dynamic_cast<const ast::EnumInstType *>( dst ) ) {
 		cost = enumCastCost(inst, dstInst, symtab, env);
-	} else if ( !inst->base->isCfa ) {
+	} else if ( inst->base->is_c_enum() ) {
 		static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicKind::SignedInt ) };
 		cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
@@ -455,6 +455,5 @@
 }
 
-void ConversionCost::postvisit( const ast::VarArgsType * varArgsType ) {
-	(void)varArgsType;
+void ConversionCost::postvisit( const ast::VarArgsType * ) {
 	if ( dynamic_cast< const ast::VarArgsType * >( dst ) ) {
 		cost = Cost::zero;
@@ -462,6 +461,5 @@
 }
 
-void ConversionCost::postvisit( const ast::ZeroType * zeroType ) {
-	(void)zeroType;
+void ConversionCost::postvisit( const ast::ZeroType * ) {
 	if ( dynamic_cast< const ast::ZeroType * >( dst ) ) {
 		cost = Cost::zero;
@@ -487,5 +485,5 @@
 		// assuming 0p is supposed to be used for pointers?
 	} else if ( auto dstAsEnumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) {
-		if ( dstAsEnumInst->base && !dstAsEnumInst->base->isCfa ) {
+		if ( dstAsEnumInst->base && dstAsEnumInst->base->is_c_enum() ) {
 			cost = Cost::safe;
 		}
@@ -493,6 +491,5 @@
 }
 
-void ConversionCost::postvisit( const ast::OneType * oneType ) {
-	(void)oneType;
+void ConversionCost::postvisit( const ast::OneType * ) {
 	if ( dynamic_cast< const ast::OneType * >( dst ) ) {
 		cost = Cost::zero;
@@ -508,5 +505,5 @@
 		}
 	} else if ( auto dstAsEnumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) {
-		if ( dstAsEnumInst->base && !dstAsEnumInst->base->isCfa ) {
+		if ( dstAsEnumInst->base && dstAsEnumInst->base->is_c_enum() ) {
 			cost = Cost::safe;
 		}
Index: src/ResolvExpr/ResolveTypeof.cpp
===================================================================
--- src/ResolvExpr/ResolveTypeof.cpp	(revision bbbff10c7298866851953ec442ea30d05e91b2a8)
+++ src/ResolvExpr/ResolveTypeof.cpp	(revision 90e683bd043dbecee5fc34eec99bc3d53f59d082)
@@ -62,5 +62,5 @@
 			// replace basetypeof(<enum>) by int
 			auto enumInst = newType.as< ast::EnumInstType >();
-			if ( enumInst && (!enumInst->base || !enumInst->base->isCfa) ) {
+			if ( enumInst && (!enumInst->base || enumInst->base->is_c_enum() ) ) {
 				newType = new ast::BasicType(
 					ast::BasicKind::SignedInt, newType->qualifiers, copy(newType->attributes) );
@@ -144,9 +144,9 @@
 
 	auto enumInst = decl->type.as<ast::EnumInstType>();
-	if ( enumInst && enumInst->base->isCfa ) {
+	if ( enumInst && !enumInst->base->is_c_enum() ) {
 		if ( auto init = decl->init.as<ast::SingleInit>() ) {
 			if ( auto initExpr = init->value.as<ast::ConstantExpr>() ) {
 				if ( initExpr->result.as<ast::ZeroType>() ) {
-					auto newInit = new ast::SingleInit( init->location, 
+					auto newInit = new ast::SingleInit( init->location,
 						ast::UntypedExpr::createCall( init->location, "lowerBound", {} )
 					);
Index: src/Validate/ImplementEnumFunc.cpp
===================================================================
--- src/Validate/ImplementEnumFunc.cpp	(revision bbbff10c7298866851953ec442ea30d05e91b2a8)
+++ src/Validate/ImplementEnumFunc.cpp	(revision 90e683bd043dbecee5fc34eec99bc3d53f59d082)
@@ -61,5 +61,4 @@
 	ast::FunctionDecl* genLabelProto() const;
 	ast::FunctionDecl* genValueProto() const;
-	ast::FunctionDecl* genQuasiValueProto() const;
 	ast::FunctionDecl* genTypeNameProto() const;
 
@@ -206,5 +205,5 @@
 
 ast::FunctionDecl* EnumAttrFuncGenerator::genValueProto() const {
-	assert (decl->isTyped());
+	assert( decl->is_typed_enum() );
 	return genProto(
 		"value",
@@ -414,5 +413,5 @@
 void EnumAttrFuncGenerator::genTypedEnumFunction(const ast::EnumAttribute attr) {
 	if (attr == ast::EnumAttribute::Value) {
-		if ( !decl->isTyped() ) return;
+		if ( !decl->is_typed_enum() ) return;
 		std::vector<ast::ptr<ast::Init>> inits = genValueInit();
 		ast::ObjectDecl* arrayProto =
@@ -483,5 +482,5 @@
 
 void ImplementEnumFunc::previsit(const ast::EnumDecl* enumDecl) {
-	if (!enumDecl->body || !enumDecl->isCfa) return;
+	if ( !enumDecl->body || enumDecl->is_c_enum() ) return;
 	ast::EnumInstType enumInst(enumDecl->name);
 	enumInst.base = enumDecl;
