Index: src/AST/Fwd.hpp
===================================================================
--- src/AST/Fwd.hpp	(revision 8f0627739771873f0409e88a71dcaaf6d43b7204)
+++ src/AST/Fwd.hpp	(revision dc3c9b1cf74abd2a63ed4ba2f5ef8ca9ee0c5512)
@@ -15,4 +15,6 @@
 
 #pragma once
+
+template<typename> struct bitfield;
 
 #include "AST/Node.hpp"
@@ -147,3 +149,21 @@
 class TranslationGlobal;
 
+// For the following types, only use the using type.
+namespace CV {
+	struct qualifier_flags;
+	using Qualifiers = bitfield<qualifier_flags>;
 }
+namespace Function {
+	struct spec_flags;
+	using Specs = bitfield<spec_flags>;
+}
+namespace Storage {
+	struct class_flags;
+	using Classes = bitfield<class_flags>;
+}
+namespace Linkage {
+	struct spec_flags;
+	using Spec = bitfield<spec_flags>;
+}
+
+}
Index: src/AST/Print.cpp
===================================================================
--- src/AST/Print.cpp	(revision 8f0627739771873f0409e88a71dcaaf6d43b7204)
+++ src/AST/Print.cpp	(revision dc3c9b1cf74abd2a63ed4ba2f5ef8ca9ee0c5512)
@@ -29,10 +29,34 @@
 namespace ast {
 
-template <typename C, typename... T>
-constexpr array<C,sizeof...(T)> make_array(T&&... values)
-{
-	return array<C,sizeof...(T)>{
-		std::forward<T>(values)...
-	};
+namespace {
+
+template<typename C, typename... T>
+constexpr array<C, sizeof...(T)> make_array( T&&... values ) {
+	return array<C, sizeof...(T)>{ std::forward<T>( values )... };
+}
+
+namespace Names {
+	static constexpr auto FuncSpecifiers = make_array<const char*>(
+		"inline", "_Noreturn", "fortran"
+	);
+
+	static constexpr auto StorageClasses = make_array<const char*>(
+		"extern", "static", "auto", "register", "__thread", "_Thread_local"
+	);
+
+	static constexpr auto Qualifiers = make_array<const char*>(
+		"const", "restrict", "volatile", "mutex", "_Atomic"
+	);
+}
+
+template<typename bits_t, size_t N>
+void print( ostream & os, const bits_t & bits,
+		const array<const char *, N> & names ) {
+	if ( !bits.any() ) return;
+	for ( size_t i = 0 ; i < N ; i += 1 ) {
+		if ( bits[i] ) {
+			os << names[i] << ' ';
+		}
+	}
 }
 
@@ -80,41 +104,4 @@
 	static const char* Names[];
 
-	struct Names {
-		static constexpr auto FuncSpecifiers = make_array<const char*>(
-			"inline", "_Noreturn", "fortran"
-		);
-
-		static constexpr auto StorageClasses = make_array<const char*>(
-			"extern", "static", "auto", "register", "__thread", "_Thread_local"
-		);
-
-		static constexpr auto Qualifiers = make_array<const char*>(
-			"const", "restrict", "volatile", "mutex", "_Atomic"
-		);
-	};
-
-	template<typename storage_t, size_t N>
-	void print(const storage_t & storage, const array<const char *, N> & Names ) {
-		if ( storage.any() ) {
-			for ( size_t i = 0; i < Names.size(); i += 1 ) {
-				if ( storage[i] ) {
-					os << Names[i] << ' ';
-				}
-			}
-		}
-	}
-
-	void print( const ast::Function::Specs & specs ) {
-		print(specs, Names::FuncSpecifiers);
-	}
-
-	void print( const ast::Storage::Classes & storage ) {
-		print(storage, Names::StorageClasses);
-	}
-
-	void print( const ast::CV::Qualifiers & qualifiers ) {
-		print(qualifiers, Names::Qualifiers);
-	}
-
 	void print( const std::vector<ast::Label> & labels ) {
 		if ( labels.empty() ) return;
@@ -230,5 +217,5 @@
 		}
 
-		print( node->storage );
+		ast::print( os, node->storage );
 		os << node->typeString();
 
@@ -272,5 +259,5 @@
 
 	void preprint( const ast::Type * node ) {
-		print( node->qualifiers );
+		ast::print( os, node->qualifiers );
 	}
 
@@ -278,10 +265,10 @@
 		print( node->forall );
 		print( node->assertions );
-		print( node->qualifiers );
+		ast::print( os, node->qualifiers );
 	}
 
 	void preprint( const ast::BaseInstType * node ) {
 		print( node->attributes );
-		print( node->qualifiers );
+		ast::print( os, node->qualifiers );
 	}
 
@@ -294,5 +281,5 @@
 		}
 
-		print( node->storage );
+		ast::print( os, node->storage );
 
 		if ( node->type ) {
@@ -338,8 +325,6 @@
 		if ( ! short_mode ) printAll( node->attributes );
 
-		print( node->storage );
-		print( node->funcSpec );
-
-
+		ast::print( os, node->storage );
+		ast::print( os, node->funcSpec );
 
 		if ( node->type && node->isTypeFixed ) {
@@ -1627,4 +1612,6 @@
 };
 
+} // namespace
+
 void print( ostream & os, const ast::Node * node, Indenter indent ) {
 	Printer printer { os, indent, false };
@@ -1637,9 +1624,15 @@
 }
 
-// Annoyingly these needed to be defined out of line to avoid undefined references.
-// The size here needs to be explicit but at least the compiler will produce an error
-// if the wrong size is specified
-constexpr array<const char*, 3> Printer::Names::FuncSpecifiers;
-constexpr array<const char*, 6> Printer::Names::StorageClasses;
-constexpr array<const char*, 5> Printer::Names::Qualifiers;
+void print( ostream & os, Function::Specs specs ) {
+	print( os, specs, Names::FuncSpecifiers );
 }
+
+void print( ostream & os, Storage::Classes storage ) {
+	print( os, storage, Names::StorageClasses );
+}
+
+void print( ostream & os, CV::Qualifiers qualifiers ) {
+	print( os, qualifiers, Names::Qualifiers );
+}
+
+} // namespace ast
Index: src/AST/Print.hpp
===================================================================
--- src/AST/Print.hpp	(revision 8f0627739771873f0409e88a71dcaaf6d43b7204)
+++ src/AST/Print.hpp	(revision dc3c9b1cf74abd2a63ed4ba2f5ef8ca9ee0c5512)
@@ -16,13 +16,10 @@
 #pragma once
 
-#include <iostream>
-#include <utility>   // for forward
+#include <iosfwd>
 
-#include "AST/Node.hpp"
+#include "AST/Fwd.hpp"
 #include "Common/Indenter.h"
 
 namespace ast {
-
-class Decl;
 
 /// Print a node with the given indenter
@@ -44,3 +41,10 @@
 }
 
+/// Print each cv-qualifier used in the set, followed by a space.
+void print( std::ostream & os, CV::Qualifiers );
+/// Print each function specifier used in the set, followed by a space.
+void print( std::ostream & os, Function::Specs );
+/// Print each storage class used in the set, followed by a space.
+void print( std::ostream & os, Storage::Classes );
+
 }
