Index: src/CodeTools/DeclStats.cc
===================================================================
--- src/CodeTools/DeclStats.cc	(revision 396ee0a9ecb5759b5ef6fcddad28460077e5ec79)
+++ src/CodeTools/DeclStats.cc	(revision 131dbb3d82aef2a9cc8891fa118693613534833d)
@@ -63,4 +63,7 @@
 			std::map<unsigned, unsigned> p_poly;   ///< Count of decls with each percentage of polymorphic elements
 			VectorMap<unsigned> n_types;           ///< Count of decls with each number of distinct types in the pack
+			/// Count of decls with each percentage of new types in lists.
+			/// Types used in the parameter list that recur in the return list are not considered to be new.
+			std::map<unsigned, unsigned> p_new;
 
 			ArgPackStats& operator+= (const ArgPackStats& o) {
@@ -71,4 +74,5 @@
 				sum(p_poly, o.p_poly);
 				sum(n_types, o.n_types);
+				sum(p_new, o.p_new);
 				
 				return *this;
@@ -86,4 +90,8 @@
 			/// Count of uses of each non-basic type
 			std::unordered_map<std::string, unsigned> compound_type_names;
+			/// Count of decls using each basic type
+			std::unordered_map<std::string, unsigned> basic_type_decls;
+			/// Count of decls using each compound type
+			std::unordered_map<std::string, unsigned> compound_type_decls;
 			/// Stats for the parameter list
 			ArgPackStats params;
@@ -98,5 +106,5 @@
 			ArgPackStats assn_returns;
 			
-			Stats() : n_decls(0), n_type_params(), by_name(), basic_type_names(), compound_type_names(), params(), returns(), n_assns(), assn_params(), assn_returns() {}
+			Stats() : n_decls(0), n_type_params(), by_name(), basic_type_names(), compound_type_names(), basic_type_decls(), compound_type_decls(), params(), returns(), n_assns(), assn_params(), assn_returns() {}
 
 		public:
@@ -107,4 +115,6 @@
 				sum( basic_type_names, o.basic_type_names );
 				sum( compound_type_names, o.compound_type_names );
+				sum( basic_type_decls, o.basic_type_decls );
+				sum( compound_type_decls, o.compound_type_decls );
 				sum( params, o.params );
 				sum( returns, o.returns );
@@ -122,9 +132,10 @@
 
 		/// Update arg pack stats based on a declaration list
-		void analyze( Stats& stats, ArgPackStats& pstats, std::list<DeclarationWithType*>& decls ) {
+		void analyze( Stats& stats, std::unordered_set<std::string>& seen, ArgPackStats& pstats, std::list<DeclarationWithType*>& decls ) {
 			std::unordered_set<std::string> types;
-			unsigned n = 0;
-			unsigned n_basic = 0;
-			unsigned n_poly = 0;
+			unsigned n = 0;        ///< number of args/returns
+			unsigned n_basic = 0;  ///< number of basic types
+			unsigned n_poly = 0;   ///< number of polymorphic types
+			unsigned n_new = 0;    ///< number of new types
 			for ( auto decl : decls ) {
 				Type* dt = decl->get_type();
@@ -135,12 +146,20 @@
 				dt->print( ss );
 				types.insert( ss.str() );
+				bool this_new = seen.insert( ss.str() ).second;
+				if ( this_new ) { ++n_new; }
 
 				if ( dynamic_cast<BasicType*>( dt ) ) {
 					++n_basic;
 					++stats.basic_type_names[ ss.str() ];
+					if ( this_new ) {
+						++stats.basic_type_decls[ ss.str() ];
+					}
 				} else if ( GenPoly::hasPolyBase( dt ) ) {
 					++n_poly;
 				} else {
 					++stats.compound_type_names[ ss.str() ];
+					if ( this_new ) {
+						++stats.compound_type_decls[ ss.str() ];
+					}
 				}
 			}
@@ -151,4 +170,5 @@
 				++pstats.p_basic[ n_basic*100/n ];
 				++pstats.p_poly[ n_poly*100/n ];
+				++pstats.p_new[ n_new*100/n ];
 			}
 			++pstats.n_types.at( types.size() );
@@ -156,6 +176,7 @@
 		
 		void analyzeFunc( FunctionType* fnTy, Stats& stats, ArgPackStats& params, ArgPackStats& returns ) {
-			analyze( stats, params, fnTy->get_parameters() );
-			analyze( stats, returns, fnTy->get_returnVals() );
+			std::unordered_set<std::string> seen;
+			analyze( stats, seen, params, fnTy->get_parameters() );
+			analyze( stats, seen, returns, fnTy->get_returnVals() );
 		}
 
@@ -275,4 +296,5 @@
 			printAllMap("%_poly_" + name, [&extract](const Stats& stats) { return extract(stats).p_poly; });
 			printAllMap("n_distinct_types_" + name, [&extract](const Stats& stats) { return extract(stats).n_types; });
+			printAllMap("%_new_types_in_" + name, [&extract](const Stats& stats) { return extract(stats).p_new; });
 		}
 		
@@ -291,6 +313,8 @@
 			printAll("basic_type_names", [](const Stats& stats) { return stats.basic_type_names.size(); });
 			printAllSparseHisto("basic_type_uses", [](const Stats& stats) { return stats.basic_type_names; });
+			printAllSparseHisto("decls_using_basic_type", [](const Stats& stats) { return stats.basic_type_decls; });
 			printAll("compound_type_names", [](const Stats& stats) { return stats.compound_type_names.size(); });
 			printAllSparseHisto("compound_type_uses", [](const Stats& stats) { return stats.compound_type_names; });
+			printAllSparseHisto("decls_using_compound_type", [](const Stats& stats) { return stats.compound_type_decls; });
 			printAllPack("params", [](const Stats& stats) { return stats.params; });
 			printAllPack("returns", [](const Stats& stats) { return stats.returns; });
